From ae1042746a0c25ac493f7278d1d37e476915d6cc Mon Sep 17 00:00:00 2001
From: Dennis Thiele <dennis.thiele@stud.hs-bochum.de>
Date: Wed, 12 Jul 2023 10:16:22 +0200
Subject: [PATCH] WS Anlegen

---
 ros2_ws/build/.built_by                       |   1 +
 ros2_ws/build/COLCON_IGNORE                   |   0
 .../sphero_mini_controller/GameWavefront.py   | 375 +++++++++
 .../WavefrontChatGpt.py                       |  53 ++
 .../WavefrontPlanner.py                       | 397 +++++++++
 .../lib/sphero_mini_controller/__init__.py    |   0
 .../lib/sphero_mini_controller/_constants.py  |  72 ++
 .../lib/sphero_mini_controller/a_star.py      | 282 +++++++
 .../sphero_mini_controller/blobErkennung.py   |  80 ++
 .../dynamicPathPlanning.py                    | 504 ++++++++++++
 .../build/lib/sphero_mini_controller/map.py   |  24 +
 .../sphero_mini_controller/maperstellen.py    |   0
 .../my_first_node copy.py                     | 183 +++++
 .../sphero_mini_controller/my_first_node.py   | 766 ++++++++++++++++++
 .../my_first_node_alt.py                      | 323 ++++++++
 .../my_first_node_komisch.py                  | 305 +++++++
 .../my_first_node_refwinkel.py                | 243 ++++++
 .../my_first_node_testfahrt.py                | 183 +++++
 .../lib/sphero_mini_controller/pfadplanung.py | 223 +++++
 .../potential_field_planning (1).py           | 199 +++++
 .../potential_field_planning.py               | 248 ++++++
 .../lib/sphero_mini_controller/sphero.py      |  22 +
 .../build/lib/sphero_mini_controller/test.py  |  23 +
 .../lib/sphero_mini_controller/treiber.py     | 638 +++++++++++++++
 .../lib/sphero_mini_controller/wavefront.py   | 154 ++++
 .../wavefront_coverage_path_planner.py        | 218 +++++
 .../sphero_mini_controller/wavefrontgpt2.py   |  76 ++
 .../sphero_mini_controller/colcon_build.rc    |   1 +
 .../colcon_command_prefix_setup_py.sh         |   1 +
 .../colcon_command_prefix_setup_py.sh.env     |  61 ++
 .../build/sphero_mini_controller/install.log  |  22 +
 .../__pycache__/sitecustomize.cpython-310.pyc | Bin 0 -> 301 bytes
 .../prefix_override/sitecustomize.py          |   3 +
 .../sphero_mini_controller.egg-info/PKG-INFO  |  12 +
 .../SOURCES.txt                               |  20 +
 .../dependency_links.txt                      |   1 +
 .../entry_points.txt                          |   3 +
 .../requires.txt                              |   1 +
 .../top_level.txt                             |   1 +
 .../sphero_mini_controller.egg-info/zip-safe  |   1 +
 ros2_ws/install/.colcon_install_layout        |   1 +
 ros2_ws/install/COLCON_IGNORE                 |   0
 ros2_ws/install/_local_setup_util_ps1.py      | 404 +++++++++
 ros2_ws/install/_local_setup_util_sh.py       | 404 +++++++++
 ros2_ws/install/local_setup.bash              | 107 +++
 ros2_ws/install/local_setup.ps1               |  55 ++
 ros2_ws/install/local_setup.sh                | 137 ++++
 ros2_ws/install/local_setup.zsh               | 120 +++
 ros2_ws/install/setup.bash                    |  31 +
 ros2_ws/install/setup.ps1                     |  29 +
 ros2_ws/install/setup.sh                      |  45 +
 ros2_ws/install/setup.zsh                     |  31 +
 .../PKG-INFO                                  |  12 +
 .../SOURCES.txt                               |  20 +
 .../dependency_links.txt                      |   1 +
 .../entry_points.txt                          |   3 +
 .../requires.txt                              |   1 +
 .../top_level.txt                             |   1 +
 .../zip-safe                                  |   1 +
 .../sphero_mini_controller/GameWavefront.py   | 375 +++++++++
 .../WavefrontChatGpt.py                       |  53 ++
 .../WavefrontPlanner.py                       | 397 +++++++++
 .../sphero_mini_controller/__init__.py        |   0
 .../__pycache__/GameWavefront.cpython-310.pyc | Bin 0 -> 8672 bytes
 .../WavefrontChatGpt.cpython-310.pyc          | Bin 0 -> 2682 bytes
 .../WavefrontPlanner.cpython-310.pyc          | Bin 0 -> 8584 bytes
 .../__pycache__/__init__.cpython-310.pyc      | Bin 0 -> 208 bytes
 .../__pycache__/_constants.cpython-310.pyc    | Bin 0 -> 2315 bytes
 .../__pycache__/a_star.cpython-310.pyc        | Bin 0 -> 7276 bytes
 .../__pycache__/blobErkennung.cpython-310.pyc | Bin 0 -> 1182 bytes
 .../__pycache__/core.cpython-310.pyc          | Bin 0 -> 18927 bytes
 .../dynamicPathPlanning.cpython-310.pyc       | Bin 0 -> 12309 bytes
 .../__pycache__/map.cpython-310.pyc           | Bin 0 -> 600 bytes
 .../__pycache__/maperstellen.cpython-310.pyc  | Bin 0 -> 212 bytes
 .../my_first_node copy.cpython-310.pyc        | Bin 0 -> 4396 bytes
 .../__pycache__/my_first_node.cpython-310.pyc | Bin 0 -> 16367 bytes
 .../my_first_node_alt.cpython-310.pyc         | Bin 0 -> 7256 bytes
 .../my_first_node_komisch.cpython-310.pyc     | Bin 0 -> 6049 bytes
 .../my_first_node_refwinkel.cpython-310.pyc   | Bin 0 -> 5129 bytes
 .../my_first_node_testfahrt.cpython-310.pyc   | Bin 0 -> 4401 bytes
 .../__pycache__/pfadplanung.cpython-310.pyc   | Bin 0 -> 5569 bytes
 ...tential_field_planning (1).cpython-310.pyc | Bin 0 -> 4688 bytes
 .../potential_field_planning.cpython-310.pyc  | Bin 0 -> 5668 bytes
 .../__pycache__/simple_moves.cpython-310.pyc  | Bin 0 -> 824 bytes
 .../__pycache__/sphero.cpython-310.pyc        | Bin 0 -> 647 bytes
 .../__pycache__/sphero_main.cpython-310.pyc   | Bin 0 -> 3471 bytes
 .../__pycache__/test.cpython-310.pyc          | Bin 0 -> 767 bytes
 .../__pycache__/treiber.cpython-310.pyc       | Bin 0 -> 18883 bytes
 .../__pycache__/wavefront.cpython-310.pyc     | Bin 0 -> 3571 bytes
 ...ront_coverage_path_planner.cpython-310.pyc | Bin 0 -> 5730 bytes
 .../__pycache__/wavefrontgpt2.cpython-310.pyc | Bin 0 -> 1823 bytes
 .../sphero_mini_controller/_constants.py      |  72 ++
 .../sphero_mini_controller/a_star.py          | 282 +++++++
 .../sphero_mini_controller/blobErkennung.py   |  80 ++
 .../sphero_mini_controller/core.py            | 638 +++++++++++++++
 .../dynamicPathPlanning.py                    | 504 ++++++++++++
 .../sphero_mini_controller/map.py             |  24 +
 .../sphero_mini_controller/maperstellen.py    |   0
 .../my_first_node copy.py                     | 183 +++++
 .../sphero_mini_controller/my_first_node.py   | 766 ++++++++++++++++++
 .../my_first_node_alt.py                      | 323 ++++++++
 .../my_first_node_komisch.py                  | 305 +++++++
 .../my_first_node_refwinkel.py                | 243 ++++++
 .../my_first_node_testfahrt.py                | 183 +++++
 .../sphero_mini_controller/pfadplanung.py     | 223 +++++
 .../potential_field_planning (1).py           | 199 +++++
 .../potential_field_planning.py               | 248 ++++++
 .../sphero_mini_controller/simple_moves.py    |  34 +
 .../sphero_mini_controller/sphero.py          |  22 +
 .../sphero_mini_controller/sphero_main.py     | 137 ++++
 .../sphero_mini_controller/test.py            |  23 +
 .../sphero_mini_controller/treiber.py         | 638 +++++++++++++++
 .../sphero_mini_controller/wavefront.py       | 154 ++++
 .../wavefront_coverage_path_planner.py        | 218 +++++
 .../sphero_mini_controller/wavefrontgpt2.py   |  76 ++
 .../lib/sphero_mini_controller/sphero_mini    |  33 +
 .../lib/sphero_mini_controller/test_node      |  33 +
 .../packages/sphero_mini_controller           |   0
 .../packages/sphero_mini_controller           |   1 +
 .../hook/ament_prefix_path.dsv                |   1 +
 .../hook/ament_prefix_path.ps1                |   3 +
 .../hook/ament_prefix_path.sh                 |   3 +
 .../hook/pythonpath.dsv                       |   1 +
 .../hook/pythonpath.ps1                       |   3 +
 .../sphero_mini_controller/hook/pythonpath.sh |   3 +
 .../share/sphero_mini_controller/package.bash |  31 +
 .../share/sphero_mini_controller/package.dsv  |   6 +
 .../share/sphero_mini_controller/package.ps1  | 116 +++
 .../share/sphero_mini_controller/package.sh   |  87 ++
 .../share/sphero_mini_controller/package.xml  |  35 +
 .../share/sphero_mini_controller/package.zsh  |  42 +
 ros2_ws/log/COLCON_IGNORE                     |   0
 .../log/build_2023-07-05_16-11-36/events.log  |  38 +
 .../build_2023-07-05_16-11-36/logger_all.log  | 126 +++
 .../sphero_mini_controller/command.log        |   2 +
 .../sphero_mini_controller/stderr.log         |   0
 .../sphero_mini_controller/stdout.log         |  22 +
 .../sphero_mini_controller/stdout_stderr.log  |  22 +
 .../sphero_mini_controller/streams.log        |  24 +
 ros2_ws/log/latest                            | Bin 0 -> 32 bytes
 ros2_ws/log/latest_build                      | Bin 0 -> 58 bytes
 .../.vscode/c_cpp_properties.json             |  20 +
 .../.vscode/settings.json                     |  13 +
 .../src/sphero_mini_controller/package.xml    |  35 +
 .../resource/sphero_conf.json                 |   3 +
 .../resource/sphero_mini_controller           |   0
 ros2_ws/src/sphero_mini_controller/setup.cfg  |   4 +
 ros2_ws/src/sphero_mini_controller/setup.py   |  27 +
 .../.vscode/c_cpp_properties.json             |  20 +
 .../.vscode/settings.json                     |  12 +
 .../WavefrontPlanner.py                       | 389 +++++++++
 .../sphero_mini_controller/__init__.py        |   0
 .../__pycache__/_constants.cpython-310.pyc    | Bin 0 -> 2282 bytes
 .../__pycache__/core.cpython-310.pyc          | Bin 0 -> 19045 bytes
 .../__pycache__/simple_moves.cpython-310.pyc  | Bin 0 -> 791 bytes
 .../sphero_mini_controller/_constants.py      |  72 ++
 .../sphero_mini_controller/blobErkennung.py   |  66 ++
 .../sphero_mini_controller/coreROS2.py        | 638 +++++++++++++++
 .../sphero_mini_controller/karte.jpg          | Bin 0 -> 161695 bytes
 .../sphero_mini_controller/sphero_conf.json   |   3 +
 .../sphero_mini_controller/sphero_mini.py     | 756 +++++++++++++++++
 .../test/test_copyright.py                    |  25 +
 .../test/test_flake8.py                       |  25 +
 .../test/test_pep257.py                       |  23 +
 164 files changed, 16285 insertions(+)
 create mode 100644 ros2_ws/build/.built_by
 create mode 100644 ros2_ws/build/COLCON_IGNORE
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/GameWavefront.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/WavefrontChatGpt.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/WavefrontPlanner.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/__init__.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/_constants.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/a_star.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/blobErkennung.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/dynamicPathPlanning.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/map.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/maperstellen.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node copy.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_alt.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_komisch.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_refwinkel.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_testfahrt.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/pfadplanung.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/potential_field_planning (1).py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/potential_field_planning.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/sphero.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/test.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/treiber.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefront.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefront_coverage_path_planner.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefrontgpt2.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/colcon_build.rc
 create mode 100644 ros2_ws/build/sphero_mini_controller/colcon_command_prefix_setup_py.sh
 create mode 100644 ros2_ws/build/sphero_mini_controller/colcon_command_prefix_setup_py.sh.env
 create mode 100644 ros2_ws/build/sphero_mini_controller/install.log
 create mode 100644 ros2_ws/build/sphero_mini_controller/prefix_override/__pycache__/sitecustomize.cpython-310.pyc
 create mode 100644 ros2_ws/build/sphero_mini_controller/prefix_override/sitecustomize.py
 create mode 100644 ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO
 create mode 100644 ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt
 create mode 100644 ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt
 create mode 100644 ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt
 create mode 100644 ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt
 create mode 100644 ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt
 create mode 100644 ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/zip-safe
 create mode 100644 ros2_ws/install/.colcon_install_layout
 create mode 100644 ros2_ws/install/COLCON_IGNORE
 create mode 100644 ros2_ws/install/_local_setup_util_ps1.py
 create mode 100644 ros2_ws/install/_local_setup_util_sh.py
 create mode 100644 ros2_ws/install/local_setup.bash
 create mode 100644 ros2_ws/install/local_setup.ps1
 create mode 100644 ros2_ws/install/local_setup.sh
 create mode 100644 ros2_ws/install/local_setup.zsh
 create mode 100644 ros2_ws/install/setup.bash
 create mode 100644 ros2_ws/install/setup.ps1
 create mode 100644 ros2_ws/install/setup.sh
 create mode 100644 ros2_ws/install/setup.zsh
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/PKG-INFO
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/SOURCES.txt
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/dependency_links.txt
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/entry_points.txt
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/requires.txt
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/top_level.txt
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/zip-safe
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/GameWavefront.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontChatGpt.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontPlanner.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__init__.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/GameWavefront.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/WavefrontChatGpt.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/WavefrontPlanner.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/__init__.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/_constants.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/a_star.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/blobErkennung.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/core.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/dynamicPathPlanning.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/map.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/maperstellen.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node copy.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_alt.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_komisch.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_refwinkel.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_testfahrt.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/pfadplanung.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/potential_field_planning (1).cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/potential_field_planning.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/simple_moves.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/sphero.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/sphero_main.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/test.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/treiber.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefront.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefront_coverage_path_planner.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefrontgpt2.cpython-310.pyc
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/_constants.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/a_star.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/blobErkennung.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/core.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/dynamicPathPlanning.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/map.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/maperstellen.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node copy.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_alt.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_komisch.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_refwinkel.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_testfahrt.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/pfadplanung.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/potential_field_planning (1).py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/potential_field_planning.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/simple_moves.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/sphero.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/sphero_main.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/test.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/treiber.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefront.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefront_coverage_path_planner.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefrontgpt2.py
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/sphero_mini
 create mode 100644 ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/test_node
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/ament_index/resource_index/packages/sphero_mini_controller
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/colcon-core/packages/sphero_mini_controller
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.dsv
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.ps1
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.sh
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.dsv
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.ps1
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.sh
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.bash
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.dsv
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.ps1
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.sh
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.xml
 create mode 100644 ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.zsh
 create mode 100644 ros2_ws/log/COLCON_IGNORE
 create mode 100644 ros2_ws/log/build_2023-07-05_16-11-36/events.log
 create mode 100644 ros2_ws/log/build_2023-07-05_16-11-36/logger_all.log
 create mode 100644 ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/command.log
 create mode 100644 ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stderr.log
 create mode 100644 ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stdout.log
 create mode 100644 ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stdout_stderr.log
 create mode 100644 ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/streams.log
 create mode 100644 ros2_ws/log/latest
 create mode 100644 ros2_ws/log/latest_build
 create mode 100644 ros2_ws/src/sphero_mini_controller/.vscode/c_cpp_properties.json
 create mode 100644 ros2_ws/src/sphero_mini_controller/.vscode/settings.json
 create mode 100644 ros2_ws/src/sphero_mini_controller/package.xml
 create mode 100644 ros2_ws/src/sphero_mini_controller/resource/sphero_conf.json
 create mode 100644 ros2_ws/src/sphero_mini_controller/resource/sphero_mini_controller
 create mode 100644 ros2_ws/src/sphero_mini_controller/setup.cfg
 create mode 100644 ros2_ws/src/sphero_mini_controller/setup.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/.vscode/c_cpp_properties.json
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/.vscode/settings.json
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/WavefrontPlanner.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__init__.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/_constants.cpython-310.pyc
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/core.cpython-310.pyc
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/simple_moves.cpython-310.pyc
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/_constants.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/blobErkennung.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/coreROS2.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/karte.jpg
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/sphero_conf.json
 create mode 100644 ros2_ws/src/sphero_mini_controller/sphero_mini_controller/sphero_mini.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/test/test_copyright.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/test/test_flake8.py
 create mode 100644 ros2_ws/src/sphero_mini_controller/test/test_pep257.py

diff --git a/ros2_ws/build/.built_by b/ros2_ws/build/.built_by
new file mode 100644
index 0000000..06e74ac
--- /dev/null
+++ b/ros2_ws/build/.built_by
@@ -0,0 +1 @@
+colcon
diff --git a/ros2_ws/build/COLCON_IGNORE b/ros2_ws/build/COLCON_IGNORE
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/GameWavefront.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/GameWavefront.py
new file mode 100644
index 0000000..aae934f
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/GameWavefront.py
@@ -0,0 +1,375 @@
+# Wavefront Planning
+# Sajad Saeedi, Andrew Davison 2017
+# Implementation is based on the following reference
+#
+# H. Choset, K. M. Lynch, S. Hutchinson, G. Kantor, W. Burgard, L. E. Kavraki and S. Thrun,
+# Principles of Robot Motion: Theory, Algorithms, and Implementations,
+# MIT Press, Boston, 2005.
+# http://www.cs.cmu.edu/afs/cs/Web/People/motionplanning/ 
+#
+# From Chapter 4.5 - Wave-Front Planner
+# This planner determines a path via gradient descent on the grid starting from the start. 
+# Essentially, the planner determines the path one pixel at a time.
+# The wave-front planner essentially forms a potential function on the grid which has one local minimum and thus is resolution complete. 
+# The planner also determines the shortest path, but at the cost of coming dangerously close to obstacles. 
+# The major drawback of this method is that the planner has to search the entire space for a path
+
+import pygame, os, math, time, random
+import numpy as np
+try:
+    import pygame
+    from pygame import surfarray
+    from pygame.locals import *
+except ImportError:
+    raise ImportError('Error Importing Pygame/surfarray')
+    
+pygame.init()
+
+SCALE = 1
+
+# set the width and height of the screen
+WIDTH = 1500/SCALE
+HEIGHT = 1000/SCALE
+
+# The region we will fill with obstacles
+PLAYFIELDCORNERS = (-3.0, -3.0, 3.0, 3.0)
+
+# Barrier locations
+barriers = []
+# barrier contents are (bx, by, visibilitymask)
+for i in range(100):
+	(bx, by) = (random.uniform(PLAYFIELDCORNERS[0], PLAYFIELDCORNERS[2]), random.uniform(PLAYFIELDCORNERS[1], PLAYFIELDCORNERS[3]))
+	barrier = [bx, by, 0]
+	barriers.append(barrier)
+
+BARRIERRADIUS = 0.1
+
+
+ROBOTRADIUS = 0.15
+W = 2 * ROBOTRADIUS
+SAFEDIST = 0.2
+BARRIERINFILATE = ROBOTRADIUS
+
+MAXVELOCITY = 0.5     #ms^(-1) max speed of each wheel
+MAXACCELERATION = 0.5 #ms^(-2) max rate we can change speed of each wheel
+
+target = (PLAYFIELDCORNERS[2] + 1.0, 0)
+
+k = 160/SCALE # pixels per metre for graphics
+u0 = WIDTH / 2
+v0 = HEIGHT / 2
+
+x = PLAYFIELDCORNERS[0] - 0.5
+y = 0.0
+theta = 0.0
+
+vL = 0.00
+vR = 0.00
+
+size = [int(WIDTH), int(HEIGHT)]
+screen = pygame.display.set_mode(size)
+black = (20,20,40)
+
+# This makes the normal mouse pointer invisible in graphics window
+pygame.mouse.set_visible(0)
+
+# time delta
+dt = 0.1
+
+
+def surfdemo_show(array_img, name):
+	"displays a surface, waits for user to continue"
+	screen = pygame.display.set_mode(array_img.shape[:2], 0, 32)
+	surfarray.blit_array(screen, array_img)
+	pygame.display.flip()
+	pygame.display.set_caption(name)
+	while 1:
+		e = pygame.event.wait()
+		if e.type == MOUSEBUTTONDOWN: break
+		if e.type == KEYDOWN: break
+
+
+def predictPosition(vL, vR, x, y, theta, dt):
+
+	# Position update in time dt
+
+	# Special cases
+	# Straight line motion
+	if (vL == vR): 
+		xnew = x + vL * dt * math.cos(theta)
+		ynew = y + vL * dt * math.sin(theta)
+		thetanew = theta
+	# Pure rotation motion
+	elif (vL == -vR):
+		xnew = x
+		ynew = y
+		thetanew = theta + ((vR - vL) * dt / W)
+	else:
+		# Rotation and arc angle of general circular motion
+		R = W / 2.0 * (vR + vL) / (vR - vL)
+		deltatheta = (vR - vL) * dt / W
+		xnew = x + R * (math.sin(deltatheta + theta) - math.sin(theta))
+		ynew = y - R * (math.cos(deltatheta + theta) - math.cos(theta))
+		thetanew = theta + deltatheta
+	
+	return (xnew, ynew, thetanew)
+
+
+def drawBarriers(barriers):
+	for barrier in barriers:
+		if(barrier[2] == 0):
+			pygame.draw.circle(screen, (0,20,80), (int(u0 + k * barrier[0]), int(v0 - k * barrier[1])), int(k * BARRIERRADIUS), 0)
+		else:
+			pygame.draw.circle(screen, (0,120,255), (int(u0 + k * barrier[0]), int(v0 - k * barrier[1])), int(k * BARRIERRADIUS), 0)
+	return
+	
+def dialtebarrieres(imgin, barriers):
+	imgout = imgin
+	for barrier in barriers:
+		if(barrier[2] == 0):
+			center_u = int(u0 + k * barrier[0])
+			center_v = int(v0 - k * barrier[1])
+			RAD = BARRIERRADIUS+BARRIERINFILATE
+			radius = int(k * (RAD))
+			radius2 = int(k * (BARRIERRADIUS))
+			points = [(x,y) for x in range(center_u-radius, center_u+radius) for y in range(center_v-radius, center_v+radius)]
+			for pt in points:
+				vu = center_u - pt[0]
+				vv = center_v - pt[1]
+				distance = math.sqrt(vv*vv + vu*vu)
+				if (distance < radius and distance > radius2 and pt[0] < WIDTH-1 and pt[1] < HEIGHT-1):
+					imgout[pt[0],pt[1],0] = 0
+					imgout[pt[0],pt[1],1] = 40
+					imgout[pt[0],pt[1],2] = 80
+	return imgout
+	
+def MakeWaveFront(imgarray, start_uv, target_uv):
+	print ("building wavefront, please wait ... ")	
+	heap = []
+	newheap = []
+
+	u = target_uv[0]
+	v = target_uv[1]
+
+	imgarray[:,:,0] = 0 # use channel 0 for planning
+	imgarray[u, v, 0] = 2
+
+	lastwave = 3 	# start by setting nodes around target to 3
+	moves = [(u + 1, v), (u - 1, v), (u, v - 1), (u, v + 1)]
+	for move in moves:
+		imgarray[move[0], move[1], 0] = 3
+		heap.append(move)
+
+	path = False
+	max_search = int(np.sqrt(WIDTH*WIDTH + HEIGHT*HEIGHT))
+	for currentwave in range(4, max_search):
+		lastwave = lastwave + 1
+		while(heap != []):
+			position = heap.pop()
+			(u, v) = position
+			moves = [(u + 1, v), (u - 1, v), (u, v + 1), (u, v - 1)]
+			for move in moves:
+				if(imgarray[move[0], move[1], 2] != 80):
+					if(imgarray[move[0], move[1], 0] == 0 and imgarray[position[0], position[1], 0] == currentwave - 1 and move[0] < WIDTH-1 and move[1] < HEIGHT-1 and move[0]>2 and move[1]>2):
+						imgarray[move[0], move[1], 0] = currentwave
+						newheap.append(move)
+					if(move == start_uv):
+						path = True
+						break 	
+			if(path == True):
+				break			
+		if(path == True):
+			break
+		heap = newheap
+		newheap = []
+	return imgarray, currentwave
+
+
+def FindPath(imgarray, start_uv, currentwave):
+	trajectory = []	
+	nextpt = start_uv
+	path = []
+	for backwave in range(currentwave-1,2,-1):
+		path.append(nextpt)
+		(u,v) = nextpt
+		values = []
+		val = []
+		moves = [(u + 1, v), (u - 1, v), (u, v + 1), (u, v - 1), (u + 1, v + 1), (u - 1, v - 1), (u + 1, v - 1), (u - 1, v - 1)]
+		for move in moves:
+			val.append(imgarray[move[0], move[1], 0])
+			if(imgarray[move[0], move[1], 0] == backwave):
+				values.append(imgarray[move[0], move[1], 0])
+		minimum = min(values)
+		indices = [i for i, v in enumerate(val) if v == minimum]
+		nextid = random.choice(indices)
+		nextpt = moves[nextid]	
+	return path
+
+def GetControl(x,y,theta, waypoint):
+	wpu = waypoint[0]
+	wpv = waypoint[1]
+	
+	vt = 0.2
+	u = u0 + k * x
+	v = v0 - k * y
+	vector = (wpu - u, -wpv + v)
+	vectorangle = math.atan2(vector[1], vector[0])
+	psi = vectorangle - theta
+
+	if(abs(psi) > (2*3.14/180)):
+		if(psi > 0):
+			vR = vt/2
+			vL = -vt/2
+		else:
+			vR = -vt/2
+			vL = vt/2
+	else:
+		wlx = x - (W/2.0) * math.sin(theta)
+		wly = y + (W/2.0) * math.cos(theta)	
+		ulx = u0 + k * wlx
+		vlx = v0 - k * wly
+		dl = math.sqrt((ulx-wpu)*(ulx-wpu) + (vlx-wpv)*(vlx-wpv))  
+		
+		wrx = x + (W/2.0) * math.sin(theta)
+		wry = y - (W/2.0) * math.cos(theta)
+		urx = u0 + k * wrx
+		vrx = v0 - k * wry
+		dr = math.sqrt((urx-wpu)*(urx-wpu) + (vrx-wpv)*(vrx-wpv))
+		
+		vR = 1*(2*vt)/(1+(dl/dr))
+		vL = 1*(2*vt - vR)
+
+	return vL, vR
+
+def AnimateRobot(x,y,theta):
+	# Draw robot
+	u = u0 + k * x
+	v = v0 - k * y
+	pygame.draw.circle(screen, (255,255,255), (int(u), int(v)), int(k * ROBOTRADIUS), 3)
+	# Draw wheels
+	# left wheel centre 
+	wlx = x - (W/2.0) * math.sin(theta)
+	wly = y + (W/2.0) * math.cos(theta)
+	ulx = u0 + k * wlx
+	vlx = v0 - k * wly
+	WHEELBLOB = 0.04
+	pygame.draw.circle(screen, (0,0,255), (int(ulx), int(vlx)), int(k * WHEELBLOB))
+	# right wheel centre 
+	wrx = x + (W/2.0) * math.sin(theta)
+	wry = y - (W/2.0) * math.cos(theta)
+	urx = u0 + k * wrx
+	vrx = v0 - k * wry
+	pygame.draw.circle(screen, (0,0,255), (int(urx), int(vrx)), int(k * WHEELBLOB))
+
+	time.sleep(dt / 5)
+	pygame.display.flip()
+	#time.sleep(0.2)
+
+def AnimateNavigation(barriers, waypint, path):
+	screen.fill(black)
+	drawBarriers(barriers)
+	
+	for pt in path:
+		screen.set_at(pt, (255,255,255))
+	
+	pygame.draw.circle(screen, (255,100,0), target_uv, int(k * ROBOTRADIUS), 0)		
+	pygame.draw.circle(screen, (255,100,0), (int(u0 + k * target[0]), int(v0 - k * target[1])), int(k * ROBOTRADIUS), 0)
+	pygame.draw.circle(screen, (255,0,255), (int(waypint[0]), int(waypint[1])), int(5))
+		
+def AnimatePath(imgarray, path, start_uv):
+	for pt in path:
+		imgarray[pt[0], pt[1], 0] = 0
+		imgarray[pt[0], pt[1], 1] = 255
+		imgarray[pt[0], pt[1], 2] = 255
+				
+	#imgarray[:,:,0] /= imgarray[:,:,0].max()/255.0
+	scalefactor = imgarray[:,:,0].max()/255.0
+	imgarray[:,:,0] = imgarray[:,:,0]/scalefactor
+	imgarray[:,:,0].astype(int)
+	imgarray[start_uv[0], start_uv[1], 0] = 0
+	imgarray[start_uv[0], start_uv[1], 1] = 255
+	imgarray[start_uv[0], start_uv[1], 2] = 255
+
+	surfdemo_show(imgarray, 'Wavefront Path Planning')	
+
+
+def GetWaypoint(x,y,theta, path, waypointIndex, waypointSeperation, target):
+	reset = False
+	waypoint = path[waypointIndex]
+	u = u0 + k * x
+	v = v0 - k * y
+	distance_to_wp = math.sqrt((waypoint[0]-u)**2+(waypoint[1]-v)**2) # todo compare distance in metrics
+	if(distance_to_wp < 3):
+		waypointIndex = waypointSeperation + waypointIndex 
+		if(waypointIndex > len(path)):
+			waypointIndex = len(path) - 1
+
+	return waypoint, reset, waypointIndex
+
+def IsAtTarget(x,y,target):
+	disttotarget = math.sqrt((x - target[0])**2 + (y - target[1])**2)
+	if (disttotarget < 0.04):
+		return True
+	else:
+		return False
+
+
+while(1):
+	start_uv  = (int(u0 + k * x), int(v0 - k * y)) 
+	target_uv = (int(u0 + k * target[0]), int(v0 - k * target[1]))
+	print ("start is: ", start_uv)
+	print ("goal  is: ", target_uv)
+
+	# prepare map of the world for plannign
+	screen.fill(black)
+	drawBarriers(barriers)
+	pygame.draw.circle(screen, (255,100,0), target_uv, int(k * ROBOTRADIUS), 0)
+	pygame.draw.circle(screen, (255,255,0), start_uv,  int(k * ROBOTRADIUS), 0)
+	imgscreen8  = pygame.surfarray.array3d(screen)
+	imgscreen16 = np.array(imgscreen8, dtype=np.uint16)
+	drawBarriers(barriers)
+	imgarray = dialtebarrieres(imgscreen16, barriers)
+	pygame.display.flip()
+	pygame.display.set_caption('Wavefront Path Planning')
+	
+	# build wavefront, given the map, start point, and target point
+	imgarray, currentwave = MakeWaveFront(imgarray, start_uv, target_uv)
+	print ("press a key to start navaigation ... ")
+
+	# find the path using the wavefront	
+	path = FindPath(imgarray, start_uv, currentwave)
+	
+	# normlaize and show the path on the map
+	AnimatePath(imgarray, path, start_uv)
+
+	# set start point
+	x = PLAYFIELDCORNERS[0] - 0.5
+	y = 0
+	theta = 0
+	waypointSeperation = 40;
+	waypointIndex = waypointSeperation;
+
+	# loop to navigate the path from start to target	
+	while(1):		
+		# get a waypoint to follow the path
+		(waypoint, reset, waypointIndex)= GetWaypoint(x,y,theta, path, waypointIndex, waypointSeperation, target)
+
+		# reset the simulation, if robot is at target
+		if (IsAtTarget(x,y,target)): 
+			target = (target[0], random.uniform(PLAYFIELDCORNERS[1], PLAYFIELDCORNERS[3]))
+			x = PLAYFIELDCORNERS[0] - 0.5
+			y = 0.0
+			theta = 0.0
+			break
+
+
+		# calculate control signals to get to the next waypoint
+		(vL, vR) = GetControl(x,y,theta, waypoint)
+
+		# Actually now move and update position based on chosen vL and vR
+		(x, y, theta) = predictPosition(vL, vR, x, y, theta, dt)
+
+		# animate 	
+		AnimateNavigation(barriers, waypoint, path)
+		AnimateRobot(x,y,theta)	
+		
\ No newline at end of file
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/WavefrontChatGpt.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/WavefrontChatGpt.py
new file mode 100644
index 0000000..a358dfa
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/WavefrontChatGpt.py
@@ -0,0 +1,53 @@
+import numpy as np
+import cv2
+import matplotlib.pyplot as plt
+import time
+
+class WaveFrontPlanner:
+    __wall = 999
+    __goal = 1
+    __nothing = '000'
+    __path = 'PATH'
+
+    def __init__(self, mask_list):
+        if not isinstance(mask_list, np.ndarray):
+            raise ValueError("Invalid input type. 'mask_list' must be a numpy array.")
+        self.__mapOfWorld = np.array([['999' if j > 200 else '000' for j in row] for row in mask_list])
+
+    def minSurroundingNodeValue(self, x, y):
+        values = [self.__mapOfWorld[x + 1][y], self.__mapOfWorld[x - 1][y],
+                  self.__mapOfWorld[x][y + 1], self.__mapOfWorld[x][y - 1]]
+        min_value = min(value for value in values if value != self.__nothing)
+        min_index = values.index(min_value) + 1
+        return min_value, min_index
+
+    def waveFrontAlgorithm(self):
+        goal_coordinates = np.where(self.__mapOfWorld == self.__goal)
+        goal_x, goal_y = goal_coordinates[0][0], goal_coordinates[1][0]
+        queue = [(goal_x, goal_y)]
+
+        while queue:
+            x, y = queue.pop(0)
+
+            if self.__mapOfWorld[x][y] == self.__nothing:
+                min_value, min_index = self.minSurroundingNodeValue(x, y)
+                self.__mapOfWorld[x][y] = min_value + 1
+                queue.append((x + 1, y))  # Move down
+                queue.append((x - 1, y))  # Move up
+                queue.append((x, y + 1))  # Move right
+                queue.append((x, y - 1))  # Move left
+
+        self.__mapOfWorld[goal_x][goal_y] = self.__goal
+
+    def visualizeMap(self):
+        plt.imshow(cv2.flip(self.__mapOfWorld, 0), cmap='hot', interpolation='nearest')
+        plt.colorbar()
+        plt.show()
+
+# Beispielverwendung:
+mask_list = np.zeros((200, 200))
+mask_list[50:150, 50:150] = 1
+
+planner = WaveFrontPlanner(mask_list)
+planner.waveFrontAlgorithm()
+planner.visualizeMap()
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/WavefrontPlanner.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/WavefrontPlanner.py
new file mode 100644
index 0000000..13cebc9
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/WavefrontPlanner.py
@@ -0,0 +1,397 @@
+############################################################################
+# WAVEFRONT ALGORITHM
+# Adapted to Python Code By Darin Velarde
+# Fri Jan 29 13:56:53 PST 2010
+# from C code from John Palmisano 
+# (www.societyofrobots.com)
+############################################################################
+import cv2
+import numpy as np
+import matplotlib.pyplot as plt
+import time
+
+class waveFrontPlanner:
+    ############################################################################
+    # WAVEFRONT ALGORITHM
+    # Adapted to Python Code By Darin Velarde
+    # Fri Jan 29 13:56:53 PST 2010
+    # from C code from John Palmisano 
+    # (www.societyofrobots.com)
+    ############################################################################
+
+    def __init__(self, mapOfWorld, slow=False):
+        self.__slow = slow
+        self.__mapOfWorld = mapOfWorld
+        if str(type(mapOfWorld)).find("numpy") != -1:
+            #If its a numpy array
+            self.__height, self.__width = self.__mapOfWorld.shape
+        else:
+            self.__height, self.__width = len(self.__mapOfWorld), len(self.__mapOfWorld[0])
+
+        self.__nothing = 000
+        self.__wall = 999
+        self.__goal = 1
+        self.__path = "PATH"
+
+        self.__finalPath = []
+
+        #Robot value
+        self.__robot = 254
+        #Robot default Location
+        self.__robot_x = 0
+        self.__robot_y = 0
+
+        #default goal location
+        self.__goal_x = 8
+        self.__goal_y = 9
+
+        #temp variables
+        self.__temp_A = 0
+        self.__temp_B = 0
+        self.__counter = 0
+        self.__steps = 0 #determine how processor intensive the algorithm was
+
+        #when searching for a node with a lower value
+        self.__minimum_node = 250
+        self.__min_node_location = 250
+        self.__new_state = 1
+        self.__old_state = 1
+        self.__reset_min = 250 #above this number is a special (wall or robot)
+    ###########################################################################
+
+    def setRobotPosition(self, x, y):
+        """
+        Sets the robot's current position
+
+        """
+
+        self.__robot_x = x
+        self.__robot_y = y
+    ###########################################################################
+
+    def setGoalPosition(self, x, y):
+        """
+        Sets the goal position.
+
+        """
+
+        self.__goal_x = x
+        self.__goal_y = y
+    ###########################################################################
+
+    def robotPosition(self):
+        return  (self.__robot_x, self.__robot_y)
+    ###########################################################################
+
+    def goalPosition(self):
+        return  (self.__goal_x, self.__goal_y)
+    ###########################################################################
+
+    def run(self, prnt=False):
+        """
+        The entry point for the robot algorithm to use wavefront propagation.
+
+        """
+
+        path = []
+        while self.__mapOfWorld[self.__robot_x][self.__robot_y] != self.__goal:
+            if self.__steps > 10000:
+                print ("Cannot find a path.")
+                return
+            #find new location to go to
+            self.__new_state = self.propagateWavefront()
+            #update location of robot
+            if self.__new_state == 1:
+                self.__robot_x -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" % (self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 2:
+                self.__robot_y += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 3:
+                self.__robot_x += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 4:
+                self.__robot_y -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            self.__old_state = self.__new_state
+        msg = "Found the goal in %i steps:\n" % self.__steps
+        msg += "mapOfWorld size= %i %i\n\n" % (self.__height, self.__width)
+        if prnt:
+            print(msg)
+            self.printMap()
+        return path
+    ###########################################################################
+
+    def propagateWavefront(self, prnt=False):
+        self.unpropagate()
+        #Old robot location was deleted, store new robot location in mapOfWorld
+        self.__mapOfWorld[self.__robot_x][self.__robot_y] = self.__robot
+        self.__path = self.__robot
+        #start location to begin scan at goal location
+        self.__mapOfWorld[self.__goal_x][self.__goal_y] = self.__goal
+        counter = 0
+        while counter < 200:  #allows for recycling until robot is found
+            x = 0
+            y = 0
+            #time.sleep(0.00001)
+            #while the mapOfWorld hasnt been fully scanned
+            while x < self.__height and y < self.__width:
+                #if this location is a wall or the goal, just ignore it
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal:
+                    #a full trail to the robot has been located, finished!
+                    minLoc = self.minSurroundingNodeValue(x, y)
+                    if minLoc < self.__reset_min and \
+                        self.__mapOfWorld[x][y] == self.__robot:
+                        if prnt:
+                            print("Finished Wavefront:\n")
+                            self.printMap()
+                        # Tell the robot to move after this return.
+                        return self.__min_node_location
+                    #record a value in to this node
+                    elif self.__minimum_node != self.__reset_min:
+                        #if this isnt here, 'nothing' will go in the location
+                        self.__mapOfWorld[x][y] = self.__minimum_node + 1
+                #go to next node and/or row
+                y += 1
+                if y == self.__width and x != self.__height:
+                    x += 1
+                    y = 0
+            #print self.__robot_x, self.__robot_y
+            if prnt:
+                print("Sweep #: %i\n" % (counter + 1))
+                self.printMap()
+            self.__steps += 1
+            counter += 1
+        return 0
+    ###########################################################################
+
+    def unpropagate(self):
+        """
+        clears old path to determine new path
+        stay within boundary
+
+        """
+
+        for x in range(0, self.__height):
+            for y in range(0, self.__width):
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal and \
+                    self.__mapOfWorld[x][y] != self.__path:
+                    #if this location is a wall or goal, just ignore it
+                    self.__mapOfWorld[x][y] = self.__nothing #clear that space
+    ###########################################################################
+
+    def minSurroundingNodeValue(self, x, y):
+        """
+        this method looks at a node and returns the lowest value around that
+        node.
+
+        """
+
+        #reset minimum
+        self.__minimum_node = self.__reset_min
+        #down
+        if x < self.__height -1:
+            if self.__mapOfWorld[x + 1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x + 1][y] != self.__nothing:
+                #find the lowest number node, and exclude empty nodes (0's)
+                self.__minimum_node = self.__mapOfWorld[x + 1][y]
+                self.__min_node_location = 3
+        #up
+        if x > 0:
+            if self.__mapOfWorld[x-1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x-1][y] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x-1][y]
+                self.__min_node_location = 1
+        #right
+        if y < self.__width -1:
+            if self.__mapOfWorld[x][y + 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y + 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y + 1]
+                self.__min_node_location = 2
+        #left
+        if y > 0:
+            if self.__mapOfWorld[x][y - 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y - 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y-1]
+                self.__min_node_location = 4
+        return self.__minimum_node
+    ###########################################################################
+
+    def printMap(self):
+        """
+        Prints out the map of this instance of the class.
+
+        """
+
+        msg = ''
+        for temp_B in range(0, self.__height):
+            for temp_A in range(0, self.__width):
+                if self.__mapOfWorld[temp_B][temp_A] == self.__wall:
+                    msg += "%04s" % "[#]"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__robot:
+                    msg += "%04s" % "-"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__goal:
+                    msg += "%04s" % "G"
+                else:
+                    msg += "%04s" % str(self.__mapOfWorld[temp_B][temp_A])
+            msg += "\n\n"
+        msg += "\n\n"
+        print(msg)
+        #
+        if self.__slow == True:
+            time.sleep(0.05)
+############################################################################
+
+class mapCreate:   
+    ############################################################################
+ 
+    def create_map(self, scale,img):
+
+        # Map erstellen
+
+        # Img Objekt
+        #cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+        #success, img = cap.read()
+        
+        #Karte von Bild
+        #succ, img = cv2.imread(2)
+        print('Original Dimensions : ',img.shape)
+        
+        scale_percent = 100-scale # percent of original size
+        width = int(img.shape[1] * scale_percent / 100)
+        height = int(img.shape[0] * scale_percent / 100)
+        dim = (width, height)
+
+        # resize image
+        resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
+        print('Resized Dimensions : ',resized.shape)
+
+        gray = cv2.cvtColor(resized, cv2.COLOR_RGB2GRAY)
+        mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+        mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+        mask_list= np.ndarray.tolist(mask)
+
+        #Markiere alle leeren Zellen mit 000 und alle Zellen mit Hinderniss mit 999
+        for i in range(0,mask.shape[0]):
+            mapOfWorld[i] = ['999' if j > 200 else '000' for j in mask_list[i]]
+        
+        mapOfWorld = np.array(mapOfWorld, dtype = int)
+        mapOfWorldSized = mapOfWorld.copy()
+        
+        e = 3
+        #Hindernisse Größer machen
+        for i in range(0,mapOfWorld.shape[0]):
+            for j in range(0,mapOfWorld.shape[1]):
+                for r in range(0,e):
+                    try:
+                        if (mapOfWorldSized[i][j] == 999):
+                            mapOfWorld[i][j+e] = 999
+                            mapOfWorld[i+e][j] = 999
+                            mapOfWorld[i-e][j] = 999
+                            mapOfWorld[i][j-e] = 999
+                            mapOfWorld[i+e][j+e] = 999
+                            mapOfWorld[i+e][j-e] = 999
+                            mapOfWorld[i-e][j+e] = 999
+                            mapOfWorld[i-e][j-e] = 999
+                    except Exception:
+                        continue
+
+        return mapOfWorld
+    ############################################################################
+
+    def scale_koord(self, sx, sy, gx, gy,scale):
+        scale_percent = 100-scale # percent of original size
+
+        sx = int(sx*scale_percent/100)
+        sy = int(sy*scale_percent/100)
+        gx = int(gx*scale_percent/100)
+        gy = int(gy*scale_percent/100)
+        
+        return sx,sy,gx,gy
+    ############################################################################
+
+    def rescale_koord(self, path,scale):
+        scale_percent = 100-scale # percent of original size100
+
+        path = np.array(path)
+
+        for i in range(len(path)):
+            path[i] = path[i]*100/scale_percent
+
+        return path
+    ############################################################################
+
+    def calc_trans(self, x, y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+###############################################################################
+
+if __name__ == "__main__":
+    """
+    X is vertical, Y is horizontal
+
+    """
+    
+    Map = mapCreate() #Map Objekt erzeugen
+    
+    #Verkleinerungsfaktor in %
+    scale = 85
+    
+    img = cv2.imread("D:/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/karte.jpg", cv2.COLOR_RGB2GRAY)
+    #cap = cv2.VideoCapture(2)
+    mapWorld = Map.create_map(scale, img)
+    height, width = img.shape[:2]
+    
+    #Angaben in Weltkoordinaten
+    sy = 300     #X-Koordinate im Weltkoordinaten System
+    sx = 200     #Y-Koordinate im Weltkoordinaten System
+    
+    gy = 700    #X-Koordinate im Weltkordinaten System
+    gx = 240    #Y-Koordinate im Weltkoordinaten System
+
+    sx,sy,gx,gy = Map.scale_koord(sx,sy,gx,gy,scale) #Kordinaten Tauschen X,Y
+
+    start = time.time()
+    planner = waveFrontPlanner(mapWorld)
+    planner.setGoalPosition(gx,gy)
+    planner.setRobotPosition(sx,sy)
+    path = planner.run(False)
+    end = time.time()
+    print("Took %f seconds to run wavefront simulation" % (end - start))
+
+    path = Map.rescale_koord(path, scale)
+    #print(path)
+#%% Plot 
+    #Programm Koordinaten
+    imgTrans = cv2.transpose(img) # X und Y-Achse im Bild tauschen
+    imgPlot, ax1 = plt.subplots()
+    
+    ax1.set_title('Programm Koordinaten')
+    ax1.imshow(imgTrans)
+    ax1.set_xlabel('[px]')
+    ax1.set_ylabel('[px]')
+    ax1.scatter(path[:,0], path[:,1], color='r')
+    
+    #Bild Koordinaten
+    imgPlot2, ax2 = plt.subplots()
+    ax2.set_title('Bild Koordinaten')
+    ax2.set_xlabel('[px]')
+    ax2.set_ylabel('[px]')
+    ax2.imshow(img)
+    ax2.scatter(path[:,1], path[:,0], color='r')
+    
+#%% Sphero Pfad
+    pathWeltX, pathWeltY = Map.calc_trans(path[:,1], path[:,0], height)
\ No newline at end of file
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/__init__.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/_constants.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/_constants.py
new file mode 100644
index 0000000..fa8a0e8
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/_constants.py
@@ -0,0 +1,72 @@
+'''
+Known Peripheral UUIDs, obtained by querying using the Bluepy module:
+=====================================================================
+Anti DOS Characteristic <00020005-574f-4f20-5370-6865726f2121>
+Battery Level Characteristic <Battery Level>
+Peripheral Preferred Connection Parameters Characteristic <Peripheral Preferred Connection Parameters>
+API V2 Characteristic <00010002-574f-4f20-5370-6865726f2121>
+DFU Control Characteristic <00020002-574f-4f20-5370-6865726f2121>
+Name Characteristic <Device Name>
+Appearance Characteristic <Appearance>
+DFU Info Characteristic <00020004-574f-4f20-5370-6865726f2121>
+Service Changed Characteristic <Service Changed>
+Unknown1 Characteristic <00020003-574f-4f20-5370-6865726f2121>
+Unknown2 Characteristic <00010003-574f-4f20-5370-6865726f2121>
+
+The rest of the values saved in the dictionaries below, were borrowed from
+@igbopie's javacript library, which is available at https://github.com/igbopie/spherov2.js
+
+'''
+
+deviceID = {"apiProcessor": 0x10,                   # 16
+            "systemInfo": 0x11,                     # 17
+            "powerInfo": 0x13,                      # 19
+            "driving": 0x16,                        # 22
+            "animatronics": 0x17,                   # 23
+            "sensor": 0x18,                         # 24
+            "something": 0x19,                      # 25
+            "userIO": 0x1a,                         # 26
+            "somethingAPI": 0x1f}                   # 31
+
+SystemInfoCommands = {"mainApplicationVersion": 0x00,   # 00
+                      "bootloaderVersion": 0x01,    # 01
+                      "something": 0x06,            # 06
+                      "something2": 0x13,           # 19
+                      "something6": 0x12,           # 18    
+                      "something7": 0x28}           # 40
+
+sendPacketConstants = {"StartOfPacket": 0x8d,       # 141
+                       "EndOfPacket": 0xd8}         # 216
+
+userIOCommandIDs = {"allLEDs": 0x0e}                # 14
+
+flags= {"isResponse": 0x01,                         # 0x01
+        "requestsResponse": 0x02,                   # 0x02
+        "requestsOnlyErrorResponse": 0x04,          # 0x04
+        "resetsInactivityTimeout": 0x08}            # 0x08
+
+powerCommandIDs={"deepSleep": 0x00,                 # 0
+                "sleep": 0x01,                      # 01
+                "batteryVoltage": 0x03,             # 03
+                "wake": 0x0D,                       # 13
+                "something": 0x05,                  # 05 
+                "something2": 0x10,                 # 16         
+                "something3": 0x04,                 # 04
+                "something4": 0x1E}                 # 30
+
+drivingCommands={"rawMotor": 0x01,                  # 1
+                 "resetHeading": 0x06,              # 6    
+                 "driveAsSphero": 0x04,             # 4
+                 "driveAsRc": 0x02,                 # 2
+                 "driveWithHeading": 0x07,          # 7
+                 "stabilization": 0x0C}             # 12
+
+sensorCommands={'sensorMask': 0x00,                 # 00
+                'sensorResponse': 0x02,             # 02
+                'configureCollision': 0x11,         # 17
+                'collisionDetectedAsync': 0x12,     # 18
+                'resetLocator': 0x13,               # 19
+                'enableCollisionAsync': 0x14,       # 20
+                'sensor1': 0x0F,                    # 15
+                'sensor2': 0x17,                    # 23
+                'configureSensorStream': 0x0C}      # 12
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/a_star.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/a_star.py
new file mode 100644
index 0000000..6d20350
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/a_star.py
@@ -0,0 +1,282 @@
+"""
+
+A* grid planning
+
+author: Atsushi Sakai(@Atsushi_twi)
+        Nikos Kanargias (nkana@tee.gr)
+
+See Wikipedia article (https://en.wikipedia.org/wiki/A*_search_algorithm)
+
+"""
+
+import math
+
+import matplotlib.pyplot as plt
+
+show_animation = True
+
+
+class AStarPlanner:
+
+    def __init__(self, ox, oy, resolution, rr):
+        """
+        Initialize grid map for a star planning
+
+        ox: x position list of Obstacles [m]
+        oy: y position list of Obstacles [m]
+        resolution: grid resolution [m]
+        rr: robot radius[m]
+        """
+
+        self.resolution = resolution
+        self.rr = rr
+        self.min_x, self.min_y = 0, 0
+        self.max_x, self.max_y = 0, 0
+        self.obstacle_map = None
+        self.x_width, self.y_width = 0, 0
+        self.motion = self.get_motion_model()
+        self.calc_obstacle_map(ox, oy)
+
+    class Node:
+        def __init__(self, x, y, cost, parent_index):
+            self.x = x  # index of grid
+            self.y = y  # index of grid
+            self.cost = cost
+            self.parent_index = parent_index
+
+        def __str__(self):
+            return str(self.x) + "," + str(self.y) + "," + str(
+                self.cost) + "," + str(self.parent_index)
+
+    def planning(self, sx, sy, gx, gy):
+        """
+        A star path search
+
+        input:
+            s_x: start x position [m]
+            s_y: start y position [m]
+            gx: goal x position [m]
+            gy: goal y position [m]
+
+        output:
+            rx: x position list of the final path
+            ry: y position list of the final path
+        """
+
+        start_node = self.Node(self.calc_xy_index(sx, self.min_x),
+                               self.calc_xy_index(sy, self.min_y), 0.0, -1)
+        goal_node = self.Node(self.calc_xy_index(gx, self.min_x),
+                              self.calc_xy_index(gy, self.min_y), 0.0, -1)
+
+        open_set, closed_set = dict(), dict()
+        open_set[self.calc_grid_index(start_node)] = start_node
+
+        while True:
+            if len(open_set) == 0:
+                print("Open set is empty..")
+                break
+
+            c_id = min(
+                open_set,
+                key=lambda o: open_set[o].cost + self.calc_heuristic(goal_node,
+                                                                     open_set[
+                                                                         o]))
+            current = open_set[c_id]
+
+            # show graph
+            if show_animation:  # pragma: no cover
+                plt.plot(self.calc_grid_position(current.x, self.min_x),
+                         self.calc_grid_position(current.y, self.min_y), "xc")
+                # for stopping simulation with the esc key.
+                plt.gcf().canvas.mpl_connect('key_release_event',
+                                             lambda event: [exit(
+                                                 0) if event.key == 'escape' else None])
+                if len(closed_set.keys()) % 10 == 0:
+                    plt.pause(0.001)
+
+            if current.x == goal_node.x and current.y == goal_node.y:
+                print("Find goal")
+                goal_node.parent_index = current.parent_index
+                goal_node.cost = current.cost
+                break
+
+            # Remove the item from the open set
+            del open_set[c_id]
+
+            # Add it to the closed set
+            closed_set[c_id] = current
+
+            # expand_grid search grid based on motion model
+            for i, _ in enumerate(self.motion):
+                node = self.Node(current.x + self.motion[i][0],
+                                 current.y + self.motion[i][1],
+                                 current.cost + self.motion[i][2], c_id)
+                n_id = self.calc_grid_index(node)
+
+                # If the node is not safe, do nothing
+                if not self.verify_node(node):
+                    continue
+
+                if n_id in closed_set:
+                    continue
+
+                if n_id not in open_set:
+                    open_set[n_id] = node  # discovered a new node
+                else:
+                    if open_set[n_id].cost > node.cost:
+                        # This path is the best until now. record it
+                        open_set[n_id] = node
+
+        rx, ry = self.calc_final_path(goal_node, closed_set)
+
+        return rx, ry
+
+    def calc_final_path(self, goal_node, closed_set):
+        # generate final course
+        rx, ry = [self.calc_grid_position(goal_node.x, self.min_x)], [
+            self.calc_grid_position(goal_node.y, self.min_y)]
+        parent_index = goal_node.parent_index
+        while parent_index != -1:
+            n = closed_set[parent_index]
+            rx.append(self.calc_grid_position(n.x, self.min_x))
+            ry.append(self.calc_grid_position(n.y, self.min_y))
+            parent_index = n.parent_index
+
+        return rx, ry
+
+    @staticmethod
+    def calc_heuristic(n1, n2):
+        w = 1.0  # weight of heuristic
+        d = w * math.hypot(n1.x - n2.x, n1.y - n2.y)
+        return d
+
+    def calc_grid_position(self, index, min_position):
+        """
+        calc grid position
+
+        :param index:
+        :param min_position:
+        :return:
+        """
+        pos = index * self.resolution + min_position
+        return pos
+
+    def calc_xy_index(self, position, min_pos):
+        return round((position - min_pos) / self.resolution)
+
+    def calc_grid_index(self, node):
+        return (node.y - self.min_y) * self.x_width + (node.x - self.min_x)
+
+    def verify_node(self, node):
+        px = self.calc_grid_position(node.x, self.min_x)
+        py = self.calc_grid_position(node.y, self.min_y)
+
+        if px < self.min_x:
+            return False
+        elif py < self.min_y:
+            return False
+        elif px >= self.max_x:
+            return False
+        elif py >= self.max_y:
+            return False
+
+        # collision check
+        if self.obstacle_map[node.x][node.y]:
+            return False
+
+        return True
+
+    def calc_obstacle_map(self, ox, oy):
+
+        self.min_x = round(min(ox))
+        self.min_y = round(min(oy))
+        self.max_x = round(max(ox))
+        self.max_y = round(max(oy))
+        print("min_x:", self.min_x)
+        print("min_y:", self.min_y)
+        print("max_x:", self.max_x)
+        print("max_y:", self.max_y)
+
+        self.x_width = round((self.max_x - self.min_x) / self.resolution)
+        self.y_width = round((self.max_y - self.min_y) / self.resolution)
+        print("x_width:", self.x_width)
+        print("y_width:", self.y_width)
+
+        # obstacle map generation
+        self.obstacle_map = [[False for _ in range(self.y_width)]
+                             for _ in range(self.x_width)]
+        for ix in range(self.x_width):
+            x = self.calc_grid_position(ix, self.min_x)
+            for iy in range(self.y_width):
+                y = self.calc_grid_position(iy, self.min_y)
+                for iox, ioy in zip(ox, oy):
+                    d = math.hypot(iox - x, ioy - y)
+                    if d <= self.rr:
+                        self.obstacle_map[ix][iy] = True
+                        break
+
+    @staticmethod
+    def get_motion_model():
+        # dx, dy, cost
+        motion = [[1, 0, 1],
+                  [0, 1, 1],
+                  [-1, 0, 1],
+                  [0, -1, 1],
+                  [-1, -1, math.sqrt(2)],
+                  [-1, 1, math.sqrt(2)],
+                  [1, -1, math.sqrt(2)],
+                  [1, 1, math.sqrt(2)]]
+
+        return motion
+
+
+def main():
+    print(__file__ + " start!!")
+
+    # start and goal position
+    sx = 10.0  # [m]
+    sy = 10.0  # [m]
+    gx = 50.0  # [m]
+    gy = 50.0  # [m]
+    grid_size = 2.0  # [m]
+    robot_radius = 1.0  # [m]
+
+    # set obstacle positions
+    ox, oy = [], []
+    for i in range(-10, 60):
+        ox.append(i)
+        oy.append(-10.0)
+    for i in range(-10, 60):
+        ox.append(60.0)
+        oy.append(i)
+    for i in range(-10, 61):
+        ox.append(i)
+        oy.append(60.0)
+    for i in range(-10, 61):
+        ox.append(-10.0)
+        oy.append(i)
+    for i in range(-10, 40):
+        ox.append(20.0)
+        oy.append(i)
+    for i in range(0, 40):
+        ox.append(40.0)
+        oy.append(60.0 - i)
+
+    if show_animation:  # pragma: no cover
+        plt.plot(ox, oy, ".k")
+        plt.plot(sx, sy, "og")
+        plt.plot(gx, gy, "xb")
+        plt.grid(True)
+        plt.axis("equal")
+
+    a_star = AStarPlanner(ox, oy, grid_size, robot_radius)
+    rx, ry = a_star.planning(sx, sy, gx, gy)
+
+    if show_animation:  # pragma: no cover
+        plt.plot(rx, ry, "-r")
+        plt.pause(0.001)
+        plt.show()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/blobErkennung.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/blobErkennung.py
new file mode 100644
index 0000000..20036f5
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/blobErkennung.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+#cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+cap = cv2.VideoCapture(4)
+
+# Set up the detector with default parameters.
+detector = cv2.SimpleBlobDetector()
+ 
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+params.filterByArea = True
+params.minArea = 20
+params.maxArea = 200
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+params.filterByInertia = True
+params.minInertiaRatio = 0.5
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+
+success, img = cap.read()
+height, width = img.shape[:2]
+
+def calc_trans(x,y):
+    yTrans = height - y
+    xTrans = x
+
+    return xTrans, yTrans
+
+while True:
+
+    success, img = cap.read()
+    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+
+    # Detect blobs.
+    keypoints = detector.detect(gray)
+
+    #print(keypoints)
+    for keyPoint in keypoints:
+        x = keyPoint.pt[0]
+        y = keyPoint.pt[1]
+        #s = keyPoint.sizekeyPoints
+
+    # Draw detected blobs as red circles.
+    # cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
+    # the size of the circle corresponds to the size of blob
+
+    im_with_keypoints = cv2.drawKeypoints(gray, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
+
+    # Show blobs
+    cv2.imshow("Keypoints", im_with_keypoints)
+
+    if cv2.waitKey(10) & 0xFF == ord('q'):
+        break
\ No newline at end of file
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/dynamicPathPlanning.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/dynamicPathPlanning.py
new file mode 100644
index 0000000..6607c85
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/dynamicPathPlanning.py
@@ -0,0 +1,504 @@
+import numpy as np
+import matplotlib.pyplot as plt
+import robotController as rc
+import mapGeneration as mg
+import random
+from controller import Robot
+
+#======[Scenario Control functions]============================================
+
+#This function causes the robot to wait some time steps before starting it's operation
+#DO NOT CHANGE THIS FUNCTION OR IT'S CALL IN THE CODE
+def waitRandomTimeSteps(turtle, stop=50):
+    initialPose = np.zeros(7)
+    initialPose[0:2] = findRobotPosition(turtle)
+    turtle.setPoseGoal(initialPose)
+    turtle.drive_goalPose()
+    nRand = random.randint(1, stop)
+    for i in range(nRand):
+        turtle.robot.step(turtle.TIME_STEP)
+    turtle.update()
+
+#=========[Example functions for finding objects in the map]===================
+
+def findTargetPosition(turtlebot):
+    mapInd = turtlebot.findInMap_FinalTarget()
+    if(len(mapInd) != 0):
+        pos = turtlebot.getPositionFromMapIndex(mapInd[0])
+    else:
+        pos = []
+    return np.array(pos, dtype=float).tolist()
+
+def findRobotPosition(turtlebot):
+    mapInds = turtlebot.findInMap_Robot()
+    robotPos = np.zeros((len(mapInds), 2))
+    for i in range(len(mapInds)):
+        pos = turtlebot.getPositionFromMapIndex(mapInds[i])
+        robotPos[i, ...] = pos
+    XYInd = np.average(robotPos, axis=0)
+    return np.array(XYInd, dtype=float).tolist()
+
+def findObstaclePositions(turtlebot):
+    mapInds = turtlebot.findInMap_Obstacles()
+    obsPos = np.zeros((len(mapInds), 2))
+    for i in range(len(mapInds)):
+        pos = turtlebot.getPositionFromMapIndex(mapInds[i])
+        obsPos[i, ...] = pos
+    return np.array(obsPos, dtype=float).tolist()
+
+#=========[Framework for own implementations of path tracking and planning]====
+
+def checkForPossibleCollisions(turtlebot, turtlePos, collisionCntr):
+    #Fill this with your collision detection between the planed path and 
+    #moving obstacles
+    hitBox = 0
+
+    faktor = 0.1
+
+    turtlePos1 = [turtlePos[0] + faktor, turtlePos[1] + faktor]
+    turtlePos2 = [turtlePos[0] + faktor, turtlePos[1] - faktor]
+    turtlePos3 = [turtlePos[0] - faktor, turtlePos[1] + faktor]
+    turtlePos4 = [turtlePos[0] - faktor, turtlePos[1] - faktor]
+
+    turtlePos5 = [turtlePos[0] + faktor, turtlePos[1]    ]
+    turtlePos6 = [turtlePos[0]    , turtlePos[1] + faktor]
+    turtlePos7 = [turtlePos[0] - faktor, turtlePos[1]    ]
+    turtlePos8 = [turtlePos[0]    , turtlePos[1] - faktor]
+
+    turtlePosBool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos))
+    turtlePos1Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos1))
+    turtlePos2Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos2))
+    turtlePos3Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos3))
+    turtlePos4Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos4))
+    turtlePos5Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos5))
+    turtlePos6Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos6))
+    turtlePos7Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos7))
+    turtlePos8Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos8))
+
+    hitBox = turtlePosBool | turtlePos1Bool | turtlePos2Bool | turtlePos3Bool | turtlePos4Bool | turtlePos5Bool | turtlePos6Bool | turtlePos7Bool | turtlePos8Bool
+
+    if(hitBox):
+        collisionCntr += 1
+        return True
+
+    if(~hitBox):
+        return False
+
+def staticPathTracking(turtlebot, path, indCntr):
+    #This delta value determines the precision of the position control during path tracking
+    #A high value leads towards a larger curve radius at corners in the path,
+    #  which might result in a smoothing of the path and keeping the velocity high.
+    #A lower value sets a higher precision for the precision control and thus, 
+    #  the robot might slow down when reaching a path point, but it stays very 
+    #  close to the original path
+    delta = 0.05
+    if(indCntr == (len(path)-1)):
+        delta = 0.01
+    #Control the turtlebot to drive towards the target position
+    isNearGoal = turtlebot.drive_goalPose(delta=delta)
+    #If the robot is close to the goal select the next goal position
+    if (isNearGoal):
+        indCntr += 1
+        i = min(indCntr, len(path))
+        if i == len(path):
+            indCntr = -1
+        else:
+            #print("Aktuelle Position Pfad: ", path[i])
+            turtlebot.setPoseGoal(path[i])
+    return indCntr
+
+def planInitialPath(turtle):
+
+    initialObstacles = findObstaclePositions(turtle)
+    initialPose = findRobotPosition(turtle)
+    initialFinalTarget = findTargetPosition(turtle)
+
+    plt.scatter(np.array(initialObstacles)[..., 0], np.array(initialObstacles)[..., 1])
+    plt.scatter(np.array(initialPose)[..., 0], np.array(initialPose)[..., 1] )
+    plt.scatter(np.array(initialFinalTarget)[..., 0], np.array(initialFinalTarget)[..., 1])
+    plt.show()
+    plt.pause(0.001)
+
+    from matplotlib import pyplot as ppl
+    from matplotlib import cm
+    import random, sys, math, os.path
+    from matplotlib.pyplot import imread
+
+    #Implementation of RRT
+
+    MAP_IMG = './karte.png'  #Black and white image for a map
+    MIN_NUM_VERT = 20  # Minimum number of vertex in the graph
+    MAX_NUM_VERT = 1500  # Maximum number of vertex in the graph
+    STEP_DISTANCE = 20  # Maximum distance between two vertex
+    SEED = None  # For random numbers
+
+    def rapidlyExploringRandomTree(ax, img, start, goal, seed=None):
+        hundreds = 100
+        seed = random.seed(seed)
+        #print("Zufallsseed: ", seed)
+        points = []
+        graph = []
+        points.append(start)
+        graph.append((start, []))
+        print('Generating and conecting random points')
+        occupied = True
+        phaseTwo = False
+
+        # Phase two values (points 5 step distances around the goal point)
+        minX = max(goal[0] - 5 * STEP_DISTANCE, 0)
+        maxX = min(goal[0] + 5 * STEP_DISTANCE, len(img[0]) - 1)
+        minY = max(goal[1] - 5 * STEP_DISTANCE, 0)
+        maxY = min(goal[1] + 5 * STEP_DISTANCE, len(img) - 1)
+
+        i = 0
+        while (goal not in points) and (len(points) < MAX_NUM_VERT):
+            if (i % 100) == 0:
+                print(i, 'points randomly generated')
+
+            if (len(points) % hundreds) == 0:
+                print(len(points), 'vertex generated')
+                hundreds = hundreds + 100
+
+            while (occupied):
+                if phaseTwo and (random.random() > 0.8):
+                    point = [random.randint(minX, maxX), random.randint(minY, maxY)]
+                else:
+                    point = [random.randint(0, len(img[0]) - 1), random.randint(0, len(img) - 1)]
+
+                if (img[point[1]][point[0]][0] * 255 == 255):
+                    occupied = False
+
+            occupied = True
+
+            nearest = findNearestPoint(points, point)
+            newPoints = connectPoints(point, nearest, img)
+            addToGraph(ax, graph, newPoints, point)
+            newPoints.pop(0)  # The first element is already in the points list
+            points.extend(newPoints)
+            ppl.draw()
+            i = i + 1
+
+            if len(points) >= MIN_NUM_VERT:
+                if not phaseTwo:
+                    print('Phase Two')
+                phaseTwo = True
+
+            if phaseTwo:
+                nearest = findNearestPoint(points, goal)
+                newPoints = connectPoints(goal, nearest, img)
+                addToGraph(ax, graph, newPoints, goal)
+                newPoints.pop(0)
+                points.extend(newPoints)
+                ppl.draw()
+
+        if goal in points:
+            print('Goal found, total vertex in graph:', len(points), 'total random points generated:', i)
+
+            path = searchPath(graph, start, [start])
+
+            for i in range(len(path) - 1):
+                ax.plot([path[i][0], path[i + 1][0]], [path[i][1], path[i + 1][1]], color='g', linestyle='-',
+                        linewidth=2)
+                ppl.draw()
+
+            print('Showing resulting map')
+            print('Final path:', path)
+            print('The final path is made from:', len(path), 'connected points')
+        else:
+            path = None
+            print('Reached maximum number of vertex and goal was not found')
+            print('Total vertex in graph:', len(points), 'total random points generated:', i)
+            print('Showing resulting map')
+
+        ppl.show()
+        return path
+
+    def searchPath(graph, point, path):
+        for i in graph:
+            if point == i[0]:
+                p = i
+
+        if p[0] == graph[-1][0]:
+            return path
+
+        for link in p[1]:
+            path.append(link)
+            finalPath = searchPath(graph, link, path)
+
+            if finalPath != None:
+                return finalPath
+            else:
+                path.pop()
+
+    def addToGraph(ax, graph, newPoints, point):
+        if len(newPoints) > 1:  # If there is anything to add to the graph
+            for p in range(len(newPoints) - 1):
+                nearest = [nearest for nearest in graph if (nearest[0] == [newPoints[p][0], newPoints[p][1]])]
+                nearest[0][1].append(newPoints[p + 1])
+                graph.append((newPoints[p + 1], []))
+
+                if not p == 0:
+                    ax.plot(newPoints[p][0], newPoints[p][1], '+k')  # First point is already painted
+                ax.plot([newPoints[p][0], newPoints[p + 1][0]], [newPoints[p][1], newPoints[p + 1][1]], color='k',
+                        linestyle='-', linewidth=1)
+
+            if point in newPoints:
+                ax.plot(point[0], point[1], '.g')  # Last point is green
+            else:
+                ax.plot(newPoints[p + 1][0], newPoints[p + 1][1], '+k')  # Last point is not green
+
+    def connectPoints(a, b, img):
+        newPoints = []
+        newPoints.append([b[0], b[1]])
+        step = [(a[0] - b[0]) / float(STEP_DISTANCE), (a[1] - b[1]) / float(STEP_DISTANCE)]
+
+        # Set small steps to check for walls
+        pointsNeeded = int(math.floor(max(math.fabs(step[0]), math.fabs(step[1]))))
+
+        if math.fabs(step[0]) > math.fabs(step[1]):
+            if step[0] >= 0:
+                step = [1, step[1] / math.fabs(step[0])]
+            else:
+                step = [-1, step[1] / math.fabs(step[0])]
+
+        else:
+            if step[1] >= 0:
+                step = [step[0] / math.fabs(step[1]), 1]
+            else:
+                step = [step[0] / math.fabs(step[1]), -1]
+
+        blocked = False
+        for i in range(pointsNeeded + 1):  # Creates points between graph and solitary point
+            for j in range(STEP_DISTANCE):  # Check if there are walls between points
+                coordX = round(newPoints[i][0] + step[0] * j)
+                coordY = round(newPoints[i][1] + step[1] * j)
+
+                if coordX == a[0] and coordY == a[1]:
+                    break
+                if coordY >= len(img) or coordX >= len(img[0]):
+                    break
+                if img[int(coordY)][int(coordX)][0] * 255 < 255:
+                    blocked = True
+                if blocked:
+                    break
+
+            if blocked:
+                break
+            if not (coordX == a[0] and coordY == a[1]):
+                newPoints.append(
+                    [newPoints[i][0] + (step[0] * STEP_DISTANCE), newPoints[i][1] + (step[1] * STEP_DISTANCE)])
+
+        if not blocked:
+            newPoints.append([a[0], a[1]])
+        return newPoints
+
+    def findNearestPoint(points, point):
+        best = (sys.maxsize, sys.maxsize, sys.maxsize)
+        for p in points:
+            if p == point:
+                continue
+            dist = math.sqrt((p[0] - point[0]) ** 2 + (p[1] - point[1]) ** 2)
+            if dist < best[2]:
+                best = (p[0], p[1], dist)
+        return (best[0], best[1])
+
+    karte = np.ones([80, 80, 3], dtype=int)
+
+    # Koordinatentransformation
+    initialObstacles = [[int(x[0] * 10), int(x[1] * 10)] for x in initialObstacles]
+    initialPose = [initialPose[0] * 10, initialPose[1] * 10]
+    initialFinalTarget = [initialFinalTarget[0] * 10, initialFinalTarget[1] * 10]
+
+    initialObstacles = [[int(x[0] + 40), int(x[1] - 40)] for x in initialObstacles]
+    initialPose = [initialPose[0] + 40, initialPose[1] - 40]
+    initialFinalTarget = [initialFinalTarget[0] + 40, initialFinalTarget[1] - 40]
+
+    initialObstacles = [[int(x[0]), int(x[1] * (-1))] for x in initialObstacles]
+    initialPose = [int(initialPose[0]), int(initialPose[1] * -1)]
+    initialFinalTarget = [int(initialFinalTarget[0]), int(initialFinalTarget[1] * -1)]
+
+    # Karte Hindernisse einzeichnen
+    rot = np.array(0, dtype=int)
+    gruen = np.array(0, dtype=int)
+    blau = np.array(0, dtype=int)
+
+    for k in initialObstacles:
+        karte[k[1], k[0], 0] = rot;
+        karte[k[1], k[0], 1] = gruen;
+        karte[k[1], k[0], 2] = blau;
+
+        karte[k[1] + 1, k[0] + 0, 0] = rot;
+        karte[k[1] + 1, k[0] + 0, 1] = gruen;
+        karte[k[1] + 1, k[0] + 0, 2] = blau;
+
+        karte[k[1] - 0, k[0] + 1, 0] = rot;
+        karte[k[1] - 0, k[0] + 1, 1] = gruen;
+        karte[k[1] - 0, k[0] + 1, 2] = blau;
+
+        karte[k[1] + 0, k[0] - 1, 0] = rot;
+        karte[k[1] + 0, k[0] - 1, 1] = gruen;
+        karte[k[1] + 0, k[0] - 1, 2] = blau;
+
+        karte[k[1] - 1, k[0] - 0, 0] = rot;
+        karte[k[1] - 1, k[0] - 0, 1] = gruen;
+        karte[k[1] - 1, k[0] - 0, 2] = blau;
+
+    #Plotten als PNG speichern
+    from PIL import Image
+    im = Image.fromarray((karte * 255).astype(np.uint8))
+    im.save('karte.png')
+
+    print('Loading map... with file \'', MAP_IMG, '\'')
+    img = imread(MAP_IMG)
+    fig = ppl.gcf()
+    fig.clf()
+    ax = fig.add_subplot(1, 1, 1)
+    ax.imshow(img, cmap=cm.Greys_r)
+    ax.axis('image')
+    ppl.draw()
+    print('Map is', len(img[0]), 'x', len(img))
+    start = initialPose
+    goal = initialFinalTarget
+
+    path = rapidlyExploringRandomTree(ax, img, start, goal, seed=SEED)
+
+    # Ruecktransformation
+    path1 = [[x[0], x[1] * (-1)] for x in path]
+    path2 = [[(x[0] - 40), (x[1] + 40)] for x in path1]
+    path3 = [[(x[0] / 10), (x[1] / 10)] for x in path2]
+
+    path3 = [[(x[0]), x[1], 0, 0, 0, 0, 0] for x in path3]
+
+    print("Umgerechneter Pfad", path3)
+
+    if len(sys.argv) > 2:
+        print('Only one argument is needed')
+    elif len(sys.argv) > 1:
+        if os.path.isfile(sys.argv[1]):
+            MAP_IMG = sys.argv[1]
+        else:
+            print(sys.argv[1], 'is not a file')
+
+    pathIndCntr = 0
+    
+    return path3, pathIndCntr
+
+#=============[Evaluation functions]===========================================
+collisionCntr = 0
+recalcCntr = 0
+def updateEval_RobotCollisions(detector):
+    global collisionCntr
+    collision = np.nan_to_num(detector.getValue(), nan=0)
+    collisionCntr += int(collision)
+    return bool(collision)
+
+#======================================[MAIN Execution]========================
+if __name__ == "__main__":
+    plotting = False
+    nPlot = 80
+    festgefahren = 0
+    #Only increase this value if the simulation is running slowly
+    TIME_STEP = 64    
+    
+    #%%=============[DO NOT CHANGE THIS PART OF THE SCRIPT]==================
+    loopCntr = 0                                                            # 
+    turtle = rc.turtlebotController(TIME_STEP, 
+        poseGoal_tcs=np.array([-0.863, -2.0, 0.0, 0.0, 0.0, 1.0, 3.14159])) #
+    detector = turtle.robot.getDevice("collisionDetector")                  #
+    detector.enable(TIME_STEP)                                              #
+                                                                            #
+    #The map will be initialized after the first timestep (Transmission)    #
+    turtle.robot.step(turtle.TIME_STEP)                                     #
+    turtle.update()                                                         #                                                              
+
+    #The map will have the dynamic objects after the second timestep        #
+    turtle.robot.step(turtle.TIME_STEP)                                     #
+    turtle.update()                                                         #
+    ScenarioFinalTarget = findTargetPosition(turtle)                        #
+                                                                            # 
+    if plotting:
+        mg.plotting_GM_plotly(turtle.mapGenerator)
+    #DO NOT CHANGE OR REMOVE THIS FUNCTION CALL AND POSITION                #
+    waitRandomTimeSteps(turtle)                                             #
+    #===============[From here you can change the script]====================
+    #%%
+    #here you should insert a function, which plans a path; the functions has to return a path and related index
+    try:
+        path, pathIndCntr = planInitialPath(turtle)
+    except TypeError:
+        print("Erste Pfadplanung nicht erfolgreich, neustart...")
+        try:
+            path, pathIndCntr = planInitialPath(turtle)
+        except TypeError:
+            print("Zweite Pfadplanung nicht erfolgreich, neustart...")
+            try:
+                path, pathIndCntr = planInitialPath(turtle)
+            except TypeError:
+                print("Dritte Pfadplanung nicht erfolgreich, neustart...")
+                exit()
+
+    turtle.setPoseGoal(path[pathIndCntr])
+    startTime = turtle.robot.getTime()
+
+    inhibitCntr = 0
+    while turtle.robot.step(turtle.TIME_STEP) != -1:
+    #%%===[DO NOT CHANGE THIS PART OF THE LOOP]==========================
+        loopCntr += 1                                                       #
+        turtle.update()
+
+        collision = checkForPossibleCollisions(turtle, findRobotPosition(turtle), collisionCntr)
+
+        if ( (plotting) & (loopCntr % nPlot == 0)):                         #
+            mg.plotting_GM_plotly(turtle.mapGenerator)                      #
+        #====[From here you can change the loop]=============================
+        #%%                
+        #Follow the static path towards the index pathIndCntr in the path
+        inhibitCntr = max(0, inhibitCntr - 1)
+
+        if(collision == False):
+            pathIndCntr = staticPathTracking(turtle, path, pathIndCntr)
+
+        if(collision == True):
+            print("Knallt")
+            turtle.stop()
+            festgefahren += 1
+
+            if(festgefahren == 10):
+                #Berechnen neue Pos
+                vorherigePos = path[pathIndCntr-1]
+                neueRichtung = [vorherigePos[0] / 2, vorherigePos[1] / 2, 0, 0, 0, 0, 0]
+                path.insert(pathIndCntr, neueRichtung)
+
+                #Fahre neue Pos an bis du da bist
+                #Wenn du da bist festgefahren 0 und hoffentlich keine Collsion mehr
+                recalcCntr += 1
+                inhibitCntr = 15
+                festgefahren = 0
+                collision = False
+
+        #This is the exit condition. Changing this is not recommended
+        if(pathIndCntr == -1):
+            break
+    #End while
+    #%%
+    print("Simulation ended")
+    print("Timesteps with collisions: ", collisionCntr)
+    print("Recalculations done: ", recalcCntr)
+    print("Simulationtime: ", turtle.robot.getTime() - startTime)
+    print("")
+    print("Recalculation")
+    print("Timesteps with collisions: ", collisionCntr)
+    print("Recalculations done: ", recalcCntr)
+    print("Simulationtime: ", turtle.robot.getTime() - startTime)
+
+    lastStateObstacles = np.array(findObstaclePositions(turtle))
+    lastStateRobotPose = np.array(findRobotPosition(turtle))
+        
+    trackRobot = np.array(turtle.trackRobot)
+    plt.scatter(lastStateObstacles[..., 0], lastStateObstacles[..., 1])
+    plt.scatter(lastStateRobotPose[..., 0], lastStateRobotPose[..., 1])
+    
+    plt.plot(trackRobot[..., 0], trackRobot[..., 1])
+    plt.scatter(turtle.poseGoal[0], turtle.poseGoal[1])
+    plt.scatter(turtle.mapGenerator.finalTarget[0], turtle.mapGenerator.finalTarget[1])
+    plt.show()
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/map.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/map.py
new file mode 100644
index 0000000..379645d
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/map.py
@@ -0,0 +1,24 @@
+#Map erstellen
+
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+img = cap.read()
+#height, width = img.shape[:2]
+
+success, img = cap.read()
+gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+mask[mask == 255] = 87
+
+mask = np.array(mask, dtype=np.uint8).view('S2').squeeze()
+
+mask[mask == b'WW'] = 'W'
+
+print(mask)
+
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/maperstellen.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/maperstellen.py
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node copy.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node copy.py
new file mode 100644
index 0000000..29f2473
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node copy.py	
@@ -0,0 +1,183 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime
+
+
+class MyNode(Node):
+
+    def __init__(self):
+        super().__init__("sphero_mini")
+        self.publisher_ = self.create_publisher(String,"Imu",5)
+        #self.get_logger().info("Hello from ROS2")
+    
+    def connect(self):
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        #    cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+        #print(i)
+
+        #self.publisher_.publish(i)
+
+
+        
+def main(args = None):
+
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+    thread.start()
+    rate = node.create_rate(2)
+
+    try:
+        while rclpy.ok():
+
+            sphero.configureSensorMask(
+                IMU_yaw=True,
+                IMU_pitch=True,
+                IMU_roll=True,
+                IMU_acc_y=True,
+                IMU_acc_z=True,
+                IMU_acc_x=True,
+                IMU_gyro_x=True,
+                IMU_gyro_y=True,
+                #IMU_gyro_z=True 
+                )
+            sphero.configureSensorStream()
+
+            sensors_values = node.get_sensors_data(sphero)
+            #rclpy.logdebug(sensors_values)
+            node.publish_imu(sensors_values, node)
+            sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn LEDs green
+
+            # Aiming:
+            sphero.setLEDColor(red = 0, green = 0, blue = 0) # Turn main LED off
+            sphero.stabilization(False) # Turn off stabilization
+            sphero.setBackLEDIntensity(255) # turn back LED on
+            sphero.wait(3) # Non-blocking pau`se
+            sphero.resetHeading() # Reset heading
+            sphero.stabilization(True) # Turn on stabilization
+            sphero.setBackLEDIntensity(0) # Turn back LED off
+
+            # Move around:
+            sphero.setLEDColor(red = 0, green = 0, blue = 255) # Turn main LED blue
+            sphero.roll(100, 0)      # roll forwards (heading = 0) at speed = 50
+
+            sphero.wait(3)         # Keep rolling for three seconds
+
+            sphero.roll(0, 0)       # stop
+            sphero.wait(1)          # Allow time to stop
+
+            sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn main LED green
+            sphero.roll(-100, 0)     # Keep facing forwards but roll backwards at speed = 50
+            sphero.wait(3)          # Keep rolling for three seconds
+
+            sphero.roll(0, 0)       # stop
+            sphero.wait(1)          # Allow time to stop
+    
+            rate.sleep()
+
+    except KeyboardInterrupt:
+        pass
+
+    rclpy.shutdown()
+    thread.join()
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node.py
new file mode 100644
index 0000000..8906b23
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node.py
@@ -0,0 +1,766 @@
+#!/usr/bin/env python3
+############################################################################
+#%% Imports
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Imu
+import threading
+from geometry_msgs.msg import Quaternion, Vector3
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini 
+import cv2
+import time
+import queue
+import matplotlib.pyplot as plt
+############################################################################
+#%% Blob Detector / Globale Variablen
+detector = cv2.SimpleBlobDetector()
+ 
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+params.filterByArea = True
+params.minArea = 10
+params.maxArea = 200
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+#params.filterByInertia = True
+#params.minInertiaRatio = 0.01
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+############################################################################
+#%% Class Video Capture
+# Bufferless VideoCapture
+# Quelle ?
+class VideoCapture:
+  def __init__(self, name):
+    self.cap = cv2.VideoCapture(name)
+    self.q = queue.Queue()
+    t = threading.Thread(target=self._reader)
+    t.daemon = True
+    t.start()
+  # read frames as soon as they are available, keeping only most recent one
+  def _reader(self):
+    while True:
+        ret, frame = self.cap.read()
+        #cv2.imshow("Cap", frame)
+
+        if not ret:
+            break
+        if not self.q.empty():
+            try:
+                self.q.get_nowait()   # discard previous (unprocessed) frame
+            except queue.Empty:
+                pass
+        self.q.put(frame)
+
+  def read(self):
+    return self.q.get()
+############################################################################
+#%% Class Sphero Node
+class MyNode(Node):
+    def __init__(self):
+        super().__init__("sphero_mini")
+    
+    def connect(self):
+        #Automatisch MAC-Adresse laden
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        # cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def get_pos(self, cap, height):
+        #zeitanfang = time.time()
+        
+        success = False
+
+        while(success == False):
+            try:
+                img = cap.read()
+
+                gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+                keypoints = detector.detect(gray)
+
+                for keyPoint in keypoints:
+                    x = keyPoint.pt[0]
+                    y = keyPoint.pt[1]
+                    success = True
+
+                xTrans, yTrans = self.calc_trans(x,y, height)
+            except Exception:
+                continue
+
+        #print("Blob X: %f Blob Y: %f" %(x,y))
+        #zeitende = time.time()
+        #print("Dauer Programmausführung:",(zeitende-zeitanfang))
+        #print("Get_Pos: X,Y:", xTrans,yTrans)
+
+        return xTrans,yTrans
+
+    def calc_offset(self, sphero, cap, height):
+        sphero.roll(100,0)
+        sphero.wait(1)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.get_pos(cap, height)
+        print("calc_offset: Ref Punkt x,y", ref)
+
+        sphero.wait(1)
+        sphero.roll(100,180)
+        sphero.wait(1)
+        sphero.roll(0,0)
+
+        startpunkt = self.get_pos(cap, height)
+        print("calc_offset: Startpunkt x,y", startpunkt)
+
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+
+        phi = np.arctan2(start_ref[1],start_ref[0])
+        phi = np.degrees(phi)
+        phi = int(-phi)
+        
+        print("Phi ohne alles:", phi)
+
+        phi = self.phi_in_range(phi)   
+
+        print("Calc_Offset: ", phi)
+
+        return phi
+
+    def calc_av(self,istPos, sollPos, cap, height):    
+        startPos = istPos
+
+        startPos = np.array(startPos)
+        sollPos = np.array(sollPos)
+
+        pktSpheroKord = sollPos - startPos
+
+        phi = np.arctan2(pktSpheroKord[1], pktSpheroKord[0])
+        phi = np.degrees(phi)
+
+        phiZiel = int(phi)
+
+        phiZiel = self.phi_in_range(phiZiel)
+
+        v = 100
+
+        #print("Calc_AV: a,v", phiZiel, v)
+
+        return phiZiel, v
+    
+    def drive_to(self,sphero, targetPos, aOffset, cap, height):
+        dmin = 20
+        pos = self.get_pos(cap, height)
+        pos = np.array(pos)
+
+        diff = targetPos - pos
+
+        d = np.linalg.norm(diff, ord = 2)
+
+        ar = []
+        ar.append(0)
+            
+        i = 1
+
+        while d > dmin:
+            a,v = self.calc_av(pos,targetPos, cap, height)
+
+            aR = -aOffset - a #Fallunterscheidung?
+            ar.append((self.phi_in_range(aR)))
+            
+            #Fahrbefehl
+            if(ar[i] != ar[i-1]):
+                sphero.roll(v, ar[i])
+                sphero.wait(0.05)
+            else:
+                sphero.wait(0.05)
+                
+            #Aktuelle Pos
+            pos = self.get_pos(cap, height)
+            pos = np.array(pos)
+            
+            #Abweichung
+            diff = targetPos - pos
+            diff = np.array(diff)
+            d = np.linalg.norm(diff, ord = 2)
+
+            i = i + 1
+
+        sphero.roll(0,0)
+        print("Ziel Erreicht")
+
+        return
+
+    def calc_trans(self,x,y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+    
+    def phi_in_range(self,phi):    
+        while(phi < 0):
+            phi = phi + 360 
+        while(phi > 360):
+            phi = phi - 360 
+        return phi  
+############################################################################
+#%% Class Wavefrontplanner
+class waveFrontPlanner:
+    ############################################################################
+    # WAVEFRONT ALGORITHM
+    # Adapted to Python Code By Darin Velarde
+    # Fri Jan 29 13:56:53 PST 2010
+    # from C code from John Palmisano 
+    # (www.societyofrobots.com)
+    ############################################################################
+
+    def __init__(self, mapOfWorld, slow=False):
+        self.__slow = slow
+        self.__mapOfWorld = mapOfWorld
+        if str(type(mapOfWorld)).find("numpy") != -1:
+            #If its a numpy array
+            self.__height, self.__width = self.__mapOfWorld.shape
+        else:
+            self.__height, self.__width = len(self.__mapOfWorld), len(self.__mapOfWorld[0])
+
+        self.__nothing = 000
+        self.__wall = 999
+        self.__goal = 1
+        self.__path = "PATH"
+
+        self.__finalPath = []
+
+        #Robot value
+        self.__robot = 254
+        #Robot default Location
+        self.__robot_x = 0
+        self.__robot_y = 0
+
+        #default goal location
+        self.__goal_x = 8
+        self.__goal_y = 9
+
+        #temp variables
+        self.__temp_A = 0
+        self.__temp_B = 0
+        self.__counter = 0
+        self.__steps = 0 #determine how processor intensive the algorithm was
+
+        #when searching for a node with a lower value
+        self.__minimum_node = 250
+        self.__min_node_location = 250
+        self.__new_state = 1
+        self.__old_state = 1
+        self.__reset_min = 250 #above this number is a special (wall or robot)
+    ###########################################################################
+
+    def setRobotPosition(self, x, y):
+        """
+        Sets the robot's current position
+
+        """
+
+        self.__robot_x = x
+        self.__robot_y = y
+    ###########################################################################
+
+    def setGoalPosition(self, x, y):
+        """
+        Sets the goal position.
+
+        """
+
+        self.__goal_x = x
+        self.__goal_y = y
+    ###########################################################################
+
+    def robotPosition(self):
+        return  (self.__robot_x, self.__robot_y)
+    ###########################################################################
+
+    def goalPosition(self):
+        return  (self.__goal_x, self.__goal_y)
+    ###########################################################################
+
+    def run(self, prnt=False):
+        """
+        The entry point for the robot algorithm to use wavefront propagation.
+
+        """
+
+        path = []
+        while self.__mapOfWorld[self.__robot_x][self.__robot_y] != self.__goal:
+            if self.__steps > 10000:
+                print ("Cannot find a path.")
+                return
+            #find new location to go to
+            self.__new_state = self.propagateWavefront()
+            #update location of robot
+            if self.__new_state == 1:
+                self.__robot_x -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" % (self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 2:
+                self.__robot_y += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 3:
+                self.__robot_x += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 4:
+                self.__robot_y -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            self.__old_state = self.__new_state
+        msg = "Found the goal in %i steps:\n" % self.__steps
+        msg += "mapOfWorld size= %i %i\n\n" % (self.__height, self.__width)
+        if prnt:
+            print(msg)
+            self.printMap()
+        return path
+    ###########################################################################
+
+    def propagateWavefront(self, prnt=False):
+        self.unpropagate()
+        #Old robot location was deleted, store new robot location in mapOfWorld
+        self.__mapOfWorld[self.__robot_x][self.__robot_y] = self.__robot
+        self.__path = self.__robot
+        #start location to begin scan at goal location
+        self.__mapOfWorld[self.__goal_x][self.__goal_y] = self.__goal
+        counter = 0
+        while counter < 200:  #allows for recycling until robot is found
+            x = 0
+            y = 0
+            #time.sleep(0.00001)
+            #while the mapOfWorld hasnt been fully scanned
+            while x < self.__height and y < self.__width:
+                #if this location is a wall or the goal, just ignore it
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal:
+                    #a full trail to the robot has been located, finished!
+                    minLoc = self.minSurroundingNodeValue(x, y)
+                    if minLoc < self.__reset_min and \
+                        self.__mapOfWorld[x][y] == self.__robot:
+                        if prnt:
+                            print("Finished Wavefront:\n")
+                            self.printMap()
+                        # Tell the robot to move after this return.
+                        return self.__min_node_location
+                    #record a value in to this node
+                    elif self.__minimum_node != self.__reset_min:
+                        #if this isnt here, 'nothing' will go in the location
+                        self.__mapOfWorld[x][y] = self.__minimum_node + 1
+                #go to next node and/or row
+                y += 1
+                if y == self.__width and x != self.__height:
+                    x += 1
+                    y = 0
+            #print self.__robot_x, self.__robot_y
+            if prnt:
+                print("Sweep #: %i\n" % (counter + 1))
+                self.printMap()
+            self.__steps += 1
+            counter += 1
+        return 0
+    ###########################################################################
+
+    def unpropagate(self):
+        """
+        clears old path to determine new path
+        stay within boundary
+
+        """
+
+        for x in range(0, self.__height):
+            for y in range(0, self.__width):
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal and \
+                    self.__mapOfWorld[x][y] != self.__path:
+                    #if this location is a wall or goal, just ignore it
+                    self.__mapOfWorld[x][y] = self.__nothing #clear that space
+    ###########################################################################
+
+    def minSurroundingNodeValue(self, x, y):
+        """
+        this method looks at a node and returns the lowest value around that
+        node.
+
+        """
+
+        #reset minimum
+        self.__minimum_node = self.__reset_min
+        #down
+        if x < self.__height -1:
+            if self.__mapOfWorld[x + 1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x + 1][y] != self.__nothing:
+                #find the lowest number node, and exclude empty nodes (0's)
+                self.__minimum_node = self.__mapOfWorld[x + 1][y]
+                self.__min_node_location = 3
+        #up
+        if x > 0:
+            if self.__mapOfWorld[x-1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x-1][y] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x-1][y]
+                self.__min_node_location = 1
+        #right
+        if y < self.__width -1:
+            if self.__mapOfWorld[x][y + 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y + 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y + 1]
+                self.__min_node_location = 2
+        #left
+        if y > 0:
+            if self.__mapOfWorld[x][y - 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y - 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y-1]
+                self.__min_node_location = 4
+        return self.__minimum_node
+    ###########################################################################
+
+    def printMap(self):
+        """
+        Prints out the map of this instance of the class.
+
+        """
+
+        msg = ''
+        for temp_B in range(0, self.__height):
+            for temp_A in range(0, self.__width):
+                if self.__mapOfWorld[temp_B][temp_A] == self.__wall:
+                    msg += "%04s" % "[#]"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__robot:
+                    msg += "%04s" % "-"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__goal:
+                    msg += "%04s" % "G"
+                else:
+                    msg += "%04s" % str(self.__mapOfWorld[temp_B][temp_A])
+            msg += "\n\n"
+        msg += "\n\n"
+        print(msg)
+        #
+        if self.__slow == True:
+            time.sleep(0.05)
+
+    def plotMap(self,img,path):
+        #Programm Koordinaten
+        print("Plotten")
+
+        imgTrans = cv2.transpose(img) # X und Y-Achse im Bild tauschen
+        imgPlot, ax1 = plt.subplots()
+        
+        ax1.set_title('Programm Koordinaten')
+        ax1.imshow(imgTrans)
+        ax1.set_xlabel('[px]')
+        ax1.set_ylabel('[px]')
+        ax1.scatter(path[:,0], path[:,1], color='r')
+        
+        #Bild Koordinaten
+        imgPlot2, ax2 = plt.subplots()
+        ax2.set_title('Bild Koordinaten')
+        ax2.set_xlabel('[px]')
+        ax2.set_ylabel('[px]')
+        ax2.imshow(img)
+        ax2.scatter(path[:,1], path[:,0], color='r')
+
+        plt.show()
+
+        return
+    
+    def getPathWelt(self,path,height,Mapobj):
+        
+        pathWeltX, pathWeltY = Mapobj.calc_trans_welt(path[:,1], path[:,0], height)
+        pathEckenX = []
+        pathEckenY = []
+
+        for i,px in enumerate(pathWeltX):
+            if (i < len(pathWeltX)-1) & (i > 0):
+                if px != pathWeltX[i+1]:
+                    if pathWeltY[i]!=pathWeltY[i-1]:
+                        pathEckenX.append(px)
+                        pathEckenY.append(pathWeltY[i])
+                if pathWeltY[i] != pathWeltY[i+1]:
+                    if pathWeltX[i]!=pathWeltX[i-1]:
+                        pathEckenX.append(px)
+                        pathEckenY.append(pathWeltY[i])
+                        
+        pathEckenX.append(pathWeltX[-1])
+        pathEckenY.append(pathWeltY[-1])
+                        
+
+        uebergabePath = []
+        for i in range(0,len(pathEckenX)):
+            uebergabePath.append((pathEckenX[i],pathEckenY[i]))
+
+        print("Ecken: ", uebergabePath)
+
+        return uebergabePath
+
+############################################################################
+#%% Class Map
+class mapCreate:   
+    ############################################################################
+ 
+    def create_map(self, scale, cap):
+
+        # Map erstellen
+
+        # Img Objekt
+        #cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+        img = cap.read()
+        
+        #Karte von Bild
+        #img = cv2.imread("D:/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/map/map.jpg")
+        print('Original Dimensions : ',img.shape)
+        
+        scale_percent = 100-scale # percent of original size
+        width = int(img.shape[1] * scale_percent / 100)
+        height = int(img.shape[0] * scale_percent / 100)
+        dim = (width, height)
+
+        # resize image
+        resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
+        print('Resized Dimensions : ',resized.shape)
+
+        gray = cv2.cvtColor(resized, cv2.COLOR_RGB2GRAY)
+        mask = cv2.inRange(gray, np.array([50]), np.array([255]))
+
+        plt.plot(mask)
+
+        mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+        mask_list= np.ndarray.tolist(mask)
+
+        #Markiere alle leeren Zellen mit 000 und alle Zellen mit Hinderniss mit 999
+        for i in range(0,mask.shape[0]):
+            mapOfWorld[i] = ['999' if j > 200 else '000' for j in mask_list[i]]
+        
+        mapOfWorld = np.array(mapOfWorld, dtype = int)
+        mapOfWorldSized = mapOfWorld.copy()
+        
+        e = 1
+        #Hindernisse Größer machen
+        for i in range(0,mapOfWorld.shape[0]):
+            for j in range(0,mapOfWorld.shape[1]):
+                for r in range(0,e):
+                    try:
+                        if (mapOfWorldSized[i][j] == 999):
+                            mapOfWorld[i][j+e] = 999
+                            mapOfWorld[i+e][j] = 999
+                            mapOfWorld[i-e][j] = 999
+                            mapOfWorld[i][j-e] = 999
+                            mapOfWorld[i+e][j+e] = 999
+                            mapOfWorld[i+e][j-e] = 999
+                            mapOfWorld[i-e][j+e] = 999
+                            mapOfWorld[i-e][j-e] = 999
+                    except Exception:
+                        continue
+                    
+        return mapOfWorld,img
+    ############################################################################
+
+    def scale_koord(self, sx, sy, gx, gy,scale):
+        scale_percent = 100-scale # percent of original size
+
+        sx = int(sx*scale_percent/100)
+        sy = int(sy*scale_percent/100)
+        gx = int(gx*scale_percent/100)
+        gy = int(gy*scale_percent/100)
+        
+        return sx,sy,gx,gy
+    ############################################################################
+
+    def rescale_koord(self, path,scale):
+        scale_percent = 100-scale # percent of original size100
+
+        path = np.array(path)
+
+        for i in range(len(path)):
+            path[i] = path[i]*100/scale_percent
+
+        return path
+    ############################################################################
+
+    def calc_trans_welt(self, x, y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+###############################################################################
+#%% Main Funktion 
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+        #rate = node.create_rate(5)
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    #cap = VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+    cap = VideoCapture(4)
+    Map = mapCreate()
+
+    img = cap.read()
+    height, width = img.shape[:2]
+
+    scale = 90
+
+    sphero.setLEDColor(255,0,0)
+    sphero.wait(1)
+    sphero.setBackLEDIntensity(0)
+    sphero.stabilization(True)
+
+    aOffset = node.calc_offset(sphero, cap, height) 
+
+    sphero.wait(1)
+
+    #while(True):
+
+    mapWorld,img = Map.create_map(scale, cap)
+    height, width = img.shape[:2]
+
+    #Befehle für WaveFrontPlanner/Maperstellung
+    sy,sx = node.get_pos(cap,height) #Aktuelle Roboter Pos in Welt
+    sy, sx = node.calc_trans(sy,sx,height)
+
+    gy = int(input("Bitte geben Sie die X-Zielkoordinate im Bild Koordinatensystem ein:"))    #X-Koordinate im Weltkoordinaten System
+    gx = int(input("Bitte geben Sie die Y-Zielkoordinate im Bild Koordinatensystem ein:"))    #Y-Koordinate im Weltkordinaten System
+
+    sx,sy,gx,gy = Map.scale_koord(sx,sy,gx,gy,scale) #Kordinaten Tauschen X,Y
+
+    start = time.time()
+    planner = waveFrontPlanner(mapWorld)
+    planner.setGoalPosition(gx,gy)
+    planner.setRobotPosition(sx,sy)
+    path = planner.run(False)
+    end = time.time()
+    print("Took %f seconds to run wavefront simulation" % (end - start))
+    
+    path = Map.rescale_koord(path, scale)
+    
+    planner.plotMap(img,path)
+
+    pathWelt = planner.getPathWelt(path,height,Map)
+
+    for p in pathWelt:
+        node.drive_to(sphero,p,aOffset,cap, height)
+        sphero.wait(1)
+
+    print("Geschafft")
+
+        #if cv2.waitKey(10) & 0xFF == ord('q'):
+         #   break
+
+    rclpy.shutdown()
+############################################################################
+#%% Main
+if __name__ == '__main__':
+    main()
+############################################################################
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_alt.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_alt.py
new file mode 100644
index 0000000..3b4ea79
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_alt.py
@@ -0,0 +1,323 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime   
+import cv2
+import time
+import queue, threading, time
+
+# Set up the detector with default parameters.
+detector = cv2.SimpleBlobDetector()
+ 
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+params.filterByArea = True
+params.minArea = 10
+params.maxArea = 200
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+#params.filterByInertia = True
+#params.minInertiaRatio = 0.01
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+
+# bufferless VideoCapture
+class VideoCapture:
+  def __init__(self, name):
+    self.cap = cv2.VideoCapture(name)
+    self.q = queue.Queue()
+    t = threading.Thread(target=self._reader)
+    t.daemon = True
+    t.start()
+  # read frames as soon as they are available, keeping only most recent one
+  def _reader(self):
+    while True:
+      ret, frame = self.cap.read()
+      if not ret:
+        break
+      if not self.q.empty():
+        try:
+          self.q.get_nowait()   # discard previous (unprocessed) frame
+        except queue.Empty:
+          pass
+      self.q.put(frame)
+
+  def read(self):
+    return self.q.get()
+
+class MyNode(Node):
+
+    def __init__(self):
+        super().__init__("sphero_mini")
+    
+    def connect(self):
+        #Automatisch MAC-Adresse laden
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        # cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def get_pos(self, cap, height):
+        zeitanfang = time.time()
+        
+        img = cap.read()
+        
+        gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+        keypoints = detector.detect(gray)
+
+        for keyPoint in keypoints:
+            x = keyPoint.pt[0]
+            y = keyPoint.pt[1]
+
+            #print("Blob X: %f Blob Y: %f" %(x,y))
+
+        zeitende = time.time()
+        #print("Dauer Programmausführung:",(zeitende-zeitanfang))
+
+        xTrans, yTrans = self.calc_trans(x,y, height)
+
+        #print("Get_Pos: X,Y:", xTrans,yTrans)
+
+        return xTrans,yTrans
+
+    def calc_offset(self, sphero, cap, height):
+        sphero.roll(100,0)
+        sphero.wait(2)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.get_pos(cap, height)
+        print("calc_offset: Ref Punkt x,y", ref)
+
+        sphero.wait(1)
+        sphero.roll(100,180)
+        sphero.wait(2)
+        sphero.roll(0,0)
+
+        startpunkt = self.get_pos(cap, height)
+        print("calc_offset: Startpunkt x,y", startpunkt)
+
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+
+        phi = np.arctan2(start_ref[1],start_ref[0])
+        phi = np.degrees(phi)
+        phi = int(phi)
+        
+        print("Phi ohne alles:", phi)
+
+        if(phi < 0):
+            phi = phi + 360        
+
+        if(phi > 360):
+            phi = phi - 360  
+
+        print("Calc_Offset: ", phi)
+
+        return phi
+
+    def calc_av(self, sollPos, cap, height):
+        
+        startPos = self.get_pos(cap, height)
+
+        startPos = np.array(startPos)
+        sollPos = np.array(sollPos)
+
+        pktSpheroKord = sollPos - startPos
+
+        phi = np.arctan2(pktSpheroKord[1], pktSpheroKord[0])
+        phi = np.degrees(phi)
+
+        phiZiel = int(phi)
+
+        if(phiZiel < 0):
+            phiZiel = phiZiel + 360 
+
+        if(phi > 360):
+            phi = phi - 360  
+
+        v = 100
+
+        print("Calc_AV: a,v", phiZiel, v)
+
+        return phiZiel, v
+    
+    def drive_to(self,sphero, targetPos, aOffset, cap, height):
+        dmin = 50
+        pos = self.get_pos(cap, height)
+        pos = np.array(pos)
+
+        diff = targetPos - pos
+
+        d = np.linalg.norm(diff, ord = 2)
+
+        while d > dmin:
+            a,v = self.calc_av(targetPos, cap, height)
+            ar = aOffset + a #Fallunterscheidung?
+
+            pos = self.get_pos(cap, height)
+            pos = np.array(pos)
+            diff = targetPos - pos
+            diff = np.array(diff)
+            d = np.linalg.norm(diff, ord = 2)
+
+            sphero.roll(v, ar)
+            time.sleep(0.1)
+
+        sphero.roll(0,ar)
+
+        return
+
+    def calc_trans(self,x,y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+    
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+        rate = node.create_rate(5)
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    cap = VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+    img = cap.read()
+    height, width = img.shape[:2]
+
+    sphero.setLEDColor(255,0,0)
+    sphero.wait(1)
+    sphero.setBackLEDIntensity(100)
+    sphero.stabilization(True)
+
+    aOffset = node.calc_offset(sphero, cap, height)
+
+    sphero.roll(100,0+aOffset)
+    sphero.wait(2)
+    sphero.roll(0,0)
+
+    sphero.wait(5)
+
+    targetPos = 117,430
+
+    node.drive_to(sphero,targetPos,aOffset,cap, height)
+     
+    rclpy.shutdown()
+
+if __name__ == '__main__':
+    main()
+
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_komisch.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_komisch.py
new file mode 100644
index 0000000..7c5dc3e
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_komisch.py
@@ -0,0 +1,305 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime   
+import cv2
+import time
+
+    
+# Img Objekt
+cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+# Set up the detector with default parameters.
+detector = cv2.SimpleBlobDetector()
+
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+#params.filterByArea = True
+#params.minArea = 100
+#params.maxArea = 1000
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+#params.filterByInertia = True
+#params.minInertiaRatio = 0.01
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+
+class MyNode(Node):
+    #Konstrukter Node Objekt
+    def __init__(self):
+        super().__init__("sphero_mini")
+        #self.publisher_ = self.create_publisher(String,"Imu",5)
+    
+    def connect(self):
+        #Automatisch MAC-Adresse laden
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        # cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def positionauslesen(self):
+        zeitanfang = time.time()
+
+        x = (-1)
+        y = (-1)
+
+        while x < 0 and y < 0:
+
+            success, img = cap.read()
+            gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+            # Detect blobs.
+            keypoints = detector.detect(gray)
+
+            #print(keypoints)
+            for keyPoint in keypoints:
+                x = keyPoint.pt[0]
+                y = keyPoint.pt[1]
+    
+            #print("Blob X: %f Blob Y: %f" %(x,y))
+        zeitende = time.time()
+        print("Dauer Programmausführung:",(zeitende-zeitanfang))
+        return (x,y)
+
+    def ref_winkel(self, sphero):
+
+        startpunkt = self.positionauslesen()
+
+        sphero.roll(100,0)
+        sphero.wait(2)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.positionauslesen()
+
+        sphero.wait(0.5)
+        sphero.roll(100,180)
+        sphero.wait(2)
+        sphero.roll(0,0)
+
+        soll = (startpunkt[0]+100,startpunkt[1])
+        
+        soll = np.array(soll)
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+        start_soll = soll-startpunkt
+
+        y = start_ref[0] * start_soll[1] - start_ref[1] * start_soll[0]
+        x = start_ref[0] * start_soll[0] + start_ref[1] * start_soll[1]
+
+        phi = np.arctan2(y,x)
+        phi = np.degrees(phi)
+        phi = int(phi)
+        
+        if(phi < 0 ):
+            phi = phi + 360        
+
+        return phi
+
+    def fahre_ziel(self, sphero, x,y, phiAbw):
+        
+        startPos = self.positionauslesen()
+        sollPos = (x,y)
+
+        startPos = np.array(startPos)
+        sollPos = np.array(sollPos)
+
+        pktSpheroKord = sollPos - startPos
+
+        phi = np.arctan2(pktSpheroKord[1], pktSpheroKord[0])
+        phi = np.degrees(phi)
+
+        phi = int(phi)
+
+        phiZiel = phiAbw - phi
+
+        if(phiZiel < 0 ):
+            phiZiel = phiZiel + 360 
+
+        print("Winkel Sphero System ", phi)
+        
+        #sollPos = (x,y)
+        #startPos = self.positionauslesen()
+        #refPos = (startPos[0]+100,startPos[1])
+
+        #sollPos = np.array(sollPos)
+        #refPos = np.array(refPos)
+        #startPos = np.array(startPos)
+
+        #start_ref = refPos-startPos
+        #start_soll = sollPos-startPos
+
+        #y = start_ref[0] * start_soll[1] - start_ref[1] * start_soll[0]
+        #x = start_ref[0] * start_soll[0] + start_ref[1] * start_soll[1]
+
+        #phi = np.arctan2(y,x)
+        #phi = np.degrees(phi)
+        #phiZiel = phiAbw - (int(phi) * -1)
+        
+        print("Zielwinkel: ", phiZiel)
+    
+        while(not(np.allclose(startPos, sollPos, atol = 50))):
+
+            sphero.roll(100, (phiZiel))
+            
+            aktPos = self.positionauslesen()
+            aktPos = np.array(aktPos)
+
+            time.sleep(0.1)
+        
+        print("Ziel erreicht")
+
+        sphero.roll(0, (0))
+
+        return
+    
+
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+        rate = node.create_rate(5)
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+
+    sphero.setLEDColor(255,0,0)
+    sphero.wait(1)
+    sphero.setBackLEDIntensity(100)
+    sphero.stabilization(True)
+
+    #Differenzwinkel auslesen
+    phiAbw = node.ref_winkel(sphero)
+    print("Abweichender Winkel Initialfahrt:", phiAbw)
+
+    sphero.wait(5)
+    sphero.roll(100, phiAbw)
+
+    sphero.wait(5)
+    node.fahre_ziel(sphero, 94,94, phiAbw)
+
+    sphero.wait(5)
+    node.fahre_ziel(sphero, 134,462, phiAbw)
+    
+    sphero.wait(5)
+    node.fahre_ziel(sphero, 581,372, phiAbw)
+
+    sphero.wait(5)
+    node.fahre_ziel(sphero, 331,308, phiAbw)
+
+    rclpy.spin()       
+    rclpy.shutdown()
+
+if __name__ == '__main__':
+    main()
+
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_refwinkel.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_refwinkel.py
new file mode 100644
index 0000000..78066a4
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_refwinkel.py
@@ -0,0 +1,243 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime
+
+class MyNode(Node):
+    #Konstrukter Node Objekt
+    def __init__(self):
+        super().__init__("sphero_mini")
+        #self.publisher_ = self.create_publisher(String,"Imu",5)
+    
+    def connect(self):
+        #Automatisch MAC-Adresse laden
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        # cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def positionauslesen(self):
+        # Standard imports
+        import cv2
+        import numpy as np;
+
+        # Img Objekt
+        cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+        # Set up the detector with default parameters.
+        detector = cv2.SimpleBlobDetector()
+
+        # Setup SimpleBlobDetector parameters.
+        params = cv2.SimpleBlobDetector_Params()
+
+        # Change thresholds
+        #params.minThreshold = 5
+        #params.maxThreshold = 500
+
+        #FIlter by Color
+        params.filterByColor = True
+        params.blobColor = 255
+
+        # Filter by Area.
+        #params.filterByArea = True
+        #params.minArea = 100
+        #params.maxArea = 1000
+
+        # Filter by Circularity
+        #params.filterByCircularity = True
+        #params.minCircularity = 0.5
+        #params.maxCircularity = 1
+
+        # Filter by Convexity
+        #params.filterByConvexity = True
+        #params.minConvexity = 0.7
+        #params.maxConvexity = 1
+
+        # Filter by Inertia
+        #params.filterByInertia = True
+        #params.minInertiaRatio = 0.01
+
+        # Create a detector with the parameters
+        detector = cv2.SimpleBlobDetector_create(params)
+
+        success, img = cap.read()
+        gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+
+        # Detect blobs.
+        keypoints = detector.detect(gray)
+
+        #print(keypoints)
+        for keyPoint in keypoints:
+            x = keyPoint.pt[0]
+            y = keyPoint.pt[1]
+            #keypointss = keyPoint.sizekeyPoints
+
+            #print("Blob X: %f Blob Y: %f" %(x,y))
+
+        # Draw detected blobs as red circles.
+        # cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
+        # the size of the circle corresponds to the size of blob
+
+        im_with_keypoints = cv2.drawKeypoints(gray, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
+
+        # Show blobs
+        cv2.imshow("Keypoints", im_with_keypoints)
+
+        return (x,y)
+
+    def ref_winkel(self, sphero, x,y):
+
+        startpunkt = self.positionauslesen()
+
+        sphero.roll(100,0)
+        sphero.wait(2)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.positionauslesen()
+
+        #print(ref)
+
+        sphero.wait(0.5)
+        sphero.roll(100,180)
+        sphero.wait(2)
+        sphero.roll(0,0)
+
+        soll = (x,y)
+        
+        soll = np.array(soll)
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+        start_soll = soll-startpunkt
+        phi = np.arccos(np.dot(start_ref,start_soll) / (np.linalg.norm(start_ref)*np.linalg.norm(start_soll)))
+        return phi
+
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+        rate = node.create_rate(5)
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    #Simple Moves, Erste Bewegung erkennen
+    #try:oll = (0,0)
+    #   while rclpy.ok():
+
+            #sphero.positionauslesen()
+            #soll = 0,0
+    phi = node.ref_winkel(sphero, 0,0)
+
+    phi = np.degrees(phi)
+
+    phi = int(phi)
+
+    print("Abweihender Winkel:", phi)
+
+    sphero.wait(0.5)
+    sphero.roll(100, (0 + phi))
+    sphero.wait(2)
+    sphero.roll(0,0)
+            
+#    except KeyboardInterrupt:
+ #       pass
+
+    rclpy.shutdown()
+  #  thread.join()
+
+if __name__ == '__main__':
+    main()
+
+    #!/usr/bin/env python3
+
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_testfahrt.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_testfahrt.py
new file mode 100644
index 0000000..29f2473
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node_testfahrt.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime
+
+
+class MyNode(Node):
+
+    def __init__(self):
+        super().__init__("sphero_mini")
+        self.publisher_ = self.create_publisher(String,"Imu",5)
+        #self.get_logger().info("Hello from ROS2")
+    
+    def connect(self):
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        #    cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+        #print(i)
+
+        #self.publisher_.publish(i)
+
+
+        
+def main(args = None):
+
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+    thread.start()
+    rate = node.create_rate(2)
+
+    try:
+        while rclpy.ok():
+
+            sphero.configureSensorMask(
+                IMU_yaw=True,
+                IMU_pitch=True,
+                IMU_roll=True,
+                IMU_acc_y=True,
+                IMU_acc_z=True,
+                IMU_acc_x=True,
+                IMU_gyro_x=True,
+                IMU_gyro_y=True,
+                #IMU_gyro_z=True 
+                )
+            sphero.configureSensorStream()
+
+            sensors_values = node.get_sensors_data(sphero)
+            #rclpy.logdebug(sensors_values)
+            node.publish_imu(sensors_values, node)
+            sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn LEDs green
+
+            # Aiming:
+            sphero.setLEDColor(red = 0, green = 0, blue = 0) # Turn main LED off
+            sphero.stabilization(False) # Turn off stabilization
+            sphero.setBackLEDIntensity(255) # turn back LED on
+            sphero.wait(3) # Non-blocking pau`se
+            sphero.resetHeading() # Reset heading
+            sphero.stabilization(True) # Turn on stabilization
+            sphero.setBackLEDIntensity(0) # Turn back LED off
+
+            # Move around:
+            sphero.setLEDColor(red = 0, green = 0, blue = 255) # Turn main LED blue
+            sphero.roll(100, 0)      # roll forwards (heading = 0) at speed = 50
+
+            sphero.wait(3)         # Keep rolling for three seconds
+
+            sphero.roll(0, 0)       # stop
+            sphero.wait(1)          # Allow time to stop
+
+            sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn main LED green
+            sphero.roll(-100, 0)     # Keep facing forwards but roll backwards at speed = 50
+            sphero.wait(3)          # Keep rolling for three seconds
+
+            sphero.roll(0, 0)       # stop
+            sphero.wait(1)          # Allow time to stop
+    
+            rate.sleep()
+
+    except KeyboardInterrupt:
+        pass
+
+    rclpy.shutdown()
+    thread.join()
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/pfadplanung.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/pfadplanung.py
new file mode 100644
index 0000000..d07a2a0
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/pfadplanung.py
@@ -0,0 +1,223 @@
+
+def planInitialPath(start, goal):
+
+    from matplotlib import pyplot as ppl
+    from matplotlib import cm
+    import random, sys, math, os.path
+    from matplotlib.pyplot import imread
+
+    #Implementation of RRT
+
+    MAP_IMG = './map.jpg'  #Black and white image for a map
+    MIN_NUM_VERT = 20  # Minimum number of vertex in the graph
+    MAX_NUM_VERT = 1500  # Maximum number of vertex in the graph
+    STEP_DISTANCE = 10  # Maximum distance between two vertex
+    SEED = None  # For random numbers
+
+    def rapidlyExploringRandomTree(ax, img, start, goal, seed=None):
+        hundreds = 100
+        seed = random.seed(seed)
+        #print("Zufallsseed: ", seed)
+        points = []
+        graph = []
+        points.append(start)
+        graph.append((start, []))
+        print('Generating and conecting random points')
+        occupied = True
+        phaseTwo = False
+
+        # Phase two values (points 5 step distances around the goal point)
+        minX = max(goal[0] - 5 * STEP_DISTANCE, 0)
+        maxX = min(goal[0] + 5 * STEP_DISTANCE, len(img[0]) - 1)
+        minY = max(goal[1] - 5 * STEP_DISTANCE, 0)
+        maxY = min(goal[1] + 5 * STEP_DISTANCE, len(img) - 1)
+
+        i = 0
+        while (goal not in points) and (len(points) < MAX_NUM_VERT):
+            if (i % 100) == 0:
+                print(i, 'points randomly generated')
+
+            if (len(points) % hundreds) == 0:
+                print(len(points), 'vertex generated')
+                hundreds = hundreds + 100
+
+            while (occupied):
+                if phaseTwo and (random.random() > 0.8):
+                    point = [random.randint(minX, maxX), random.randint(minY, maxY)]
+                else:
+                    point = [random.randint(0, len(img[0]) - 1), random.randint(0, len(img) - 1)]
+
+                if (img[point[1]][point[0]][0] * 255 == 255):
+                    occupied = False
+
+            occupied = True
+
+            nearest = findNearestPoint(points, point)
+            newPoints = connectPoints(point, nearest, img)
+            addToGraph(ax, graph, newPoints, point)
+            newPoints.pop(0)  # The first element is already in the points list
+            points.extend(newPoints)
+            ppl.draw()
+            i = i + 1
+
+            if len(points) >= MIN_NUM_VERT:
+                if not phaseTwo:
+                    print('Phase Two')
+                phaseTwo = True
+
+            if phaseTwo:
+                nearest = findNearestPoint(points, goal)
+                newPoints = connectPoints(goal, nearest, img)
+                addToGraph(ax, graph, newPoints, goal)
+                newPoints.pop(0)
+                points.extend(newPoints)
+                ppl.draw()
+
+        if goal in points:
+            print('Goal found, total vertex in graph:', len(points), 'total random points generated:', i)
+
+            path = searchPath(graph, start, [start])
+
+            for i in range(len(path) - 1):
+                ax.plot([path[i][0], path[i + 1][0]], [path[i][1], path[i + 1][1]], color='g', linestyle='-',
+                        linewidth=2)
+                ppl.draw()
+
+            print('Showing resulting map')
+            print('Final path:', path)
+            print('The final path is made from:', len(path), 'connected points')
+        else:
+            path = None
+            print('Reached maximum number of vertex and goal was not found')
+            print('Total vertex in graph:', len(points), 'total random points generated:', i)
+            print('Showing resulting map')
+
+        ppl.show()
+        return path
+
+    def searchPath(graph, point, path):
+        for i in graph:
+            if point == i[0]:
+                p = i
+
+        if p[0] == graph[-1][0]:
+            return path
+
+        for link in p[1]:
+            path.append(link)
+            finalPath = searchPath(graph, link, path)
+
+            if finalPath != None:
+                return finalPath
+            else:
+                path.pop()
+
+    def addToGraph(ax, graph, newPoints, point):
+        if len(newPoints) > 1:  # If there is anything to add to the graph
+            for p in range(len(newPoints) - 1):
+                nearest = [nearest for nearest in graph if (nearest[0] == [newPoints[p][0], newPoints[p][1]])]
+                nearest[0][1].append(newPoints[p + 1])
+                graph.append((newPoints[p + 1], []))
+
+                if not p == 0:
+                    ax.plot(newPoints[p][0], newPoints[p][1], '+k')  # First point is already painted
+                ax.plot([newPoints[p][0], newPoints[p + 1][0]], [newPoints[p][1], newPoints[p + 1][1]], color='k',
+                        linestyle='-', linewidth=1)
+
+            if point in newPoints:
+                ax.plot(point[0], point[1], '.g')  # Last point is green
+            else:
+                ax.plot(newPoints[p + 1][0], newPoints[p + 1][1], '+k')  # Last point is not green
+
+    def connectPoints(a, b, img):
+        newPoints = []
+        newPoints.append([b[0], b[1]])
+        step = [(a[0] - b[0]) / float(STEP_DISTANCE), (a[1] - b[1]) / float(STEP_DISTANCE)]
+
+        # Set small steps to check for walls
+        pointsNeeded = int(math.floor(max(math.fabs(step[0]), math.fabs(step[1]))))
+
+        if math.fabs(step[0]) > math.fabs(step[1]):
+            if step[0] >= 0:
+                step = [1, step[1] / math.fabs(step[0])]
+            else:
+                step = [-1, step[1] / math.fabs(step[0])]
+
+        else:
+            if step[1] >= 0:
+                step = [step[0] / math.fabs(step[1]), 1]
+            else:
+                step = [step[0] / math.fabs(step[1]), -1]
+
+        blocked = False
+        for i in range(pointsNeeded + 1):  # Creates points between graph and solitary point
+            for j in range(STEP_DISTANCE):  # Check if there are walls between points
+                coordX = round(newPoints[i][0] + step[0] * j)
+                coordY = round(newPoints[i][1] + step[1] * j)
+
+                if coordX == a[0] and coordY == a[1]:
+                    break
+                if coordY >= len(img) or coordX >= len(img[0]):
+                    break
+                if img[int(coordY)][int(coordX)][0] * 255 < 255:
+                    blocked = True
+                if blocked:
+                    break
+
+            if blocked:
+                break
+            if not (coordX == a[0] and coordY == a[1]):
+                newPoints.append(
+                    [newPoints[i][0] + (step[0] * STEP_DISTANCE), newPoints[i][1] + (step[1] * STEP_DISTANCE)])
+
+        if not blocked:
+            newPoints.append([a[0], a[1]])
+        return newPoints
+
+    def findNearestPoint(points, point):
+        best = (sys.maxsize, sys.maxsize, sys.maxsize)
+        for p in points:
+            if p == point:
+                continue
+            dist = math.sqrt((p[0] - point[0]) ** 2 + (p[1] - point[1]) ** 2)
+            if dist < best[2]:
+                best = (p[0], p[1], dist)
+        return (best[0], best[1])
+
+    # Standard imports
+    import cv2
+    import numpy as np;
+ 
+    # Img Objekt
+    cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+    val, frame = cap.read()
+    inverted_image = np.invert(frame)
+    cv2.imwrite("map.jpg", inverted_image)
+
+    print('Loading map... with file \'', MAP_IMG, '\'')
+    img = imread(MAP_IMG)
+    fig = ppl.gcf()
+    fig.clf()
+    ax = fig.add_subplot(1, 1, 1)
+    ax.imshow(img, cmap=cm.Greys_r)
+    ax.axis('image')
+    ppl.draw()
+    print('Map is', len(img[0]), 'x', len(img))
+
+    path = rapidlyExploringRandomTree(ax, img, start, goal, seed=SEED)
+
+    if len(sys.argv) > 2:
+        print('Only one argument is needed')
+    elif len(sys.argv) > 1:
+        if os.path.isfile(sys.argv[1]):
+            MAP_IMG = sys.argv[1]
+        else:
+            print(sys.argv[1], 'is not a file')
+
+    pathIndCntr = 0
+    
+    return path, pathIndCntr
+
+start = (200,200)
+ziel = (450, 450)
+planInitialPath(start,  ziel)
\ No newline at end of file
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/potential_field_planning (1).py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/potential_field_planning (1).py
new file mode 100644
index 0000000..8f136b5
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/potential_field_planning (1).py	
@@ -0,0 +1,199 @@
+"""
+
+Potential Field based path planner
+
+author: Atsushi Sakai (@Atsushi_twi)
+
+Ref:
+https://www.cs.cmu.edu/~motionplanning/lecture/Chap4-Potential-Field_howie.pdf
+
+"""
+
+from collections import deque
+import numpy as np
+import matplotlib.pyplot as plt
+
+# Parameters
+KP = 5.0  # attractive potential gain
+ETA = 100.0  # repulsive potential gain
+AREA_WIDTH = 30.0  # potential area width [m]
+# the number of previous positions used to check oscillations
+OSCILLATIONS_DETECTION_LENGTH = 3
+
+show_animation = True
+
+
+def calc_potential_field(gx, gy, ox, oy, reso, rr, sx, sy):
+    minx = min(min(ox), sx, gx) - AREA_WIDTH / 2.0
+    miny = min(min(oy), sy, gy) - AREA_WIDTH / 2.0
+    maxx = max(max(ox), sx, gx) + AREA_WIDTH / 2.0
+    maxy = max(max(oy), sy, gy) + AREA_WIDTH / 2.0
+    xw = int(round((maxx - minx) / reso))
+    yw = int(round((maxy - miny) / reso))
+
+    # calc each potential
+    pmap = [[0.0 for i in range(yw)] for i in range(xw)]
+
+    for ix in range(xw):
+        x = ix * reso + minx
+
+        for iy in range(yw):
+            y = iy * reso + miny
+            ug = calc_attractive_potential(x, y, gx, gy)
+            uo = calc_repulsive_potential(x, y, ox, oy, rr)
+            uf = ug + uo
+            pmap[ix][iy] = uf
+
+    return pmap, minx, miny
+
+
+def calc_attractive_potential(x, y, gx, gy):
+    return 0.5 * KP * np.hypot(x - gx, y - gy)
+
+
+def calc_repulsive_potential(x, y, ox, oy, rr):
+    # search nearest obstacle
+    minid = -1
+    dmin = float("inf")
+    for i, _ in enumerate(ox):
+        d = np.hypot(x - ox[i], y - oy[i])
+        if dmin >= d:
+            dmin = d
+            minid = i
+
+    # calc repulsive potential
+    dq = np.hypot(x - ox[minid], y - oy[minid])
+
+    if dq <= rr:
+        if dq <= 0.1:
+            dq = 0.1
+
+        return 0.5 * ETA * (1.0 / dq - 1.0 / rr) ** 2
+    else:
+        return 0.0
+
+
+def get_motion_model():
+    # dx, dy
+    motion = [[1, 0],
+              [0, 1],
+              [-1, 0],
+              [0, -1],
+              [-1, -1],
+              [-1, 1],
+              [1, -1],
+              [1, 1]]
+
+    return motion
+
+
+def oscillations_detection(previous_ids, ix, iy):
+    previous_ids.append((ix, iy))
+
+    if (len(previous_ids) > OSCILLATIONS_DETECTION_LENGTH):
+        previous_ids.popleft()
+
+    # check if contains any duplicates by copying into a set
+    previous_ids_set = set()
+    for index in previous_ids:
+        if index in previous_ids_set:
+            return True
+        else:
+            previous_ids_set.add(index)
+    return False
+
+
+def potential_field_planning(sx, sy, gx, gy, ox, oy, reso, rr):
+
+    # calc potential field
+    pmap, minx, miny = calc_potential_field(gx, gy, ox, oy, reso, rr, sx, sy)
+
+    # search path
+    d = np.hypot(sx - gx, sy - gy)
+    ix = round((sx - minx) / reso)
+    iy = round((sy - miny) / reso)
+    gix = round((gx - minx) / reso)
+    giy = round((gy - miny) / reso)
+
+    if show_animation:
+        draw_heatmap(pmap)
+        # for stopping simulation with the esc key.
+        plt.gcf().canvas.mpl_connect('key_release_event',
+                lambda event: [exit(0) if event.key == 'escape' else None])
+        plt.plot(ix, iy, "*k")
+        plt.plot(gix, giy, "*m")
+
+    rx, ry = [sx], [sy]
+    motion = get_motion_model()
+    previous_ids = deque()
+
+    while d >= reso:
+        minp = float("inf")
+        minix, miniy = -1, -1
+        for i, _ in enumerate(motion):
+            inx = int(ix + motion[i][0])
+            iny = int(iy + motion[i][1])
+            if inx >= len(pmap) or iny >= len(pmap[0]) or inx < 0 or iny < 0:
+                p = float("inf")  # outside area
+                print("outside potential!")
+            else:
+                p = pmap[inx][iny]
+            if minp > p:
+                minp = p
+                minix = inx
+                miniy = iny
+        ix = minix
+        iy = miniy
+        xp = ix * reso + minx
+        yp = iy * reso + miny
+        d = np.hypot(gx - xp, gy - yp)
+        rx.append(xp)
+        ry.append(yp)
+
+        if (oscillations_detection(previous_ids, ix, iy)):
+            print("Oscillation detected at ({},{})!".format(ix, iy))
+            break
+
+        if show_animation:
+            plt.plot(ix, iy, ".r")
+            plt.pause(0.01)
+
+    print("Goal!!")
+
+    return rx, ry
+
+
+def draw_heatmap(data):
+    data = np.array(data).T
+    plt.pcolor(data, vmax=100.0, cmap=plt.cm.Blues)
+
+
+def main():
+    print("potential_field_planning start")
+
+    sx = 0.0  # start x position [m]
+    sy = 10.0  # start y positon [m]
+    gx = 30.0  # goal x position [m]
+    gy = 30.0  # goal y position [m]
+    grid_size = 0.5  # potential grid size [m]
+    robot_radius = 5.0  # robot radius [m]
+
+    ox = [15.0, 5.0, 20.0, 25.0]  # obstacle x position list [m]
+    oy = [25.0, 15.0, 26.0, 25.0]  # obstacle y position list [m]
+
+    if show_animation:
+        plt.grid(True)
+        plt.axis("equal")
+
+    # path generation
+    _, _ = potential_field_planning(
+        sx, sy, gx, gy, ox, oy, grid_size, robot_radius)
+
+    if show_animation:
+        plt.show()
+
+
+if __name__ == '__main__':
+    print(__file__ + " start!!")
+    main()
+    print(__file__ + " Done!!")
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/potential_field_planning.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/potential_field_planning.py
new file mode 100644
index 0000000..c28279d
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/potential_field_planning.py
@@ -0,0 +1,248 @@
+"""
+
+Potential Field based path planner
+
+author: Atsushi Sakai (@Atsushi_twi)
+
+Ref:
+https://www.cs.cmu.edu/~motionplanning/lecture/Chap4-Potential-Field_howie.pdf
+
+"""
+
+from collections import deque
+import numpy as np
+import matplotlib.pyplot as plt
+
+# Parameters
+KP = 10.0  # attractive potential gain
+ETA = 300.0  # repulsive potential gain
+AREA_WIDTH = 704.0  # potential area width [m]
+# the number of previous positions used to check oscillations
+OSCILLATIONS_DETECTION_LENGTH = 3
+
+show_animation = True
+
+px = []
+py = []
+
+def calc_potential_field(gx, gy, ox, oy, reso, rr, sx, sy):
+    minx = min(min(ox), sx, gx) - AREA_WIDTH / 2.0
+    miny = min(min(oy), sy, gy) - AREA_WIDTH / 2.0
+    maxx = max(max(ox), sx, gx) + AREA_WIDTH / 2.0
+    maxy = max(max(oy), sy, gy) + AREA_WIDTH / 2.0
+    xw = int(round((maxx - minx) / reso))
+    yw = int(round((maxy - miny) / reso))
+
+    # calc each potential
+    pmap = [[0.0 for i in range(yw)] for i in range(xw)]
+
+    for ix in range(xw):
+        x = ix * reso + minx
+
+        for iy in range(yw):
+            y = iy * reso + miny
+            ug = calc_attractive_potential(x, y, gx, gy)
+            uo = calc_repulsive_potential(x, y, ox, oy, rr)
+            uf = ug + uo
+            pmap[ix][iy] = uf
+
+    return pmap, minx, miny
+
+
+def calc_attractive_potential(x, y, gx, gy):
+    return 0.5 * KP * np.hypot(x - gx, y - gy)
+
+
+def calc_repulsive_potential(x, y, ox, oy, rr):
+    # search nearest obstacle
+    minid = -1
+    dmin = float("inf")
+    for i, _ in enumerate(ox):
+        d = np.hypot(x - ox[i], y - oy[i])
+        if dmin >= d:
+            dmin = d
+            minid = i
+
+    # calc repulsive potential
+    dq = np.hypot(x - ox[minid], y - oy[minid])
+
+    if dq <= rr:
+        if dq <= 0.1:
+            dq = 0.1
+
+        return 0.5 * ETA * (1.0 / dq - 1.0 / rr) ** 2
+    else:
+        return 0.0
+
+
+def get_motion_model():
+    # dx, dy
+    motion = [[1, 0],
+              [0, 1],
+              [-1, 0],
+              [0, -1],
+              [-1, -1],
+              [-1, 1],
+              [1, -1],
+              [1, 1]]
+
+    return motion
+
+
+def oscillations_detection(previous_ids, ix, iy):
+    previous_ids.append((ix, iy))
+
+    if (len(previous_ids) > OSCILLATIONS_DETECTION_LENGTH):
+        previous_ids.popleft()
+
+    # check if contains any duplicates by copying into a set
+    previous_ids_set = set()
+    for index in previous_ids:
+        if index in previous_ids_set:
+            return True
+        else:
+            previous_ids_set.add(index)
+    return False
+
+
+def potential_field_planning(sx, sy, gx, gy, ox, oy, reso, rr):
+
+    # calc potential field
+    pmap, minx, miny = calc_potential_field(gx, gy, ox, oy, reso, rr, sx, sy)
+
+    # search path
+    d = np.hypot(sx - gx, sy - gy)
+    ix = round((sx - minx) / reso)
+    iy = round((sy - miny) / reso)
+    gix = round((gx - minx) / reso)
+    giy = round((gy - miny) / reso)
+
+    if show_animation:
+        draw_heatmap(pmap)
+        # for stopping simulation with the esc key.
+        plt.gcf().canvas.mpl_connect('key_release_event',
+                lambda event: [exit(0) if event.key == 'escape' else None])
+        plt.plot(ix, iy, "*k")
+        plt.plot(gix, giy, "*m")
+
+    rx, ry = [sx], [sy]
+    motion = get_motion_model()
+    previous_ids = deque()
+
+    while d >= reso:
+        minp = float("inf")
+        minix, miniy = -1, -1
+        for i, _ in enumerate(motion):
+            inx = int(ix + motion[i][0])
+            iny = int(iy + motion[i][1])
+            if inx >= len(pmap) or iny >= len(pmap[0]) or inx < 0 or iny < 0:
+                p = float("inf")  # outside area
+                print("outside potential!")
+            else:
+                p = pmap[inx][iny]
+            if minp > p:
+                minp = p
+                minix = inx
+                miniy = iny
+        ix = minix
+        iy = miniy
+        xp = ix * reso + minx
+        yp = iy * reso + miny
+        d = np.hypot(gx - xp, gy - yp)
+        rx.append(xp)
+        ry.append(yp)
+
+        if (oscillations_detection(previous_ids, ix, iy)):
+            print("Oscillation detected at ({},{})!".format(ix, iy))
+            break
+
+        if show_animation:
+            px.append(ix)
+            py.append(iy)
+            plt.plot(ix, iy, ".r")
+            plt.pause(0.01)
+
+    print("Goal!!")
+
+    return rx, ry
+
+
+def draw_heatmap(data):
+    data = np.array(data).T
+    plt.pcolor(data, vmax=100.0, cmap=plt.cm.Blues)
+
+
+def create_map():
+    # Map erstellen
+    # Standard imports
+    import cv2
+    import numpy as np;
+    
+    # Img Objekt
+    #cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+    #success, img = cap.read()
+
+    gray = cv2.imread("/home/ubuntu/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/map/map.jpg",cv2.IMREAD_GRAYSCALE)
+
+    #gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+    mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+    mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+
+    mask_list= np.ndarray.tolist(mask)
+
+    for i in range(0,mask.shape[0]):
+        mapOfWorld[i] = ['W' if j > 200 else ' ' for j in mask_list[i]]
+
+    #mapOfWorld[200][200] = 'R' #Start Pos
+    #mapOfWorld[300][300] = 'G' #Ziel Pos
+
+    return mapOfWorld
+
+
+def create_obsticles(mapOfWorld):
+    ox = []
+    oy = []
+
+    mapOfWorld = np.array(mapOfWorld)
+
+    for i in range(0,mapOfWorld.shape[0]):
+        for j in range(0,mapOfWorld.shape[1]):
+            if mapOfWorld[i][j] == 'W':
+                ox.append(i)
+                oy.append(j)
+
+    return ox,oy
+
+def main():
+    print("potential_field_planning start")
+
+    mapOfWorld = create_map()
+
+    sx = 50  # start x position [m]
+    sy = 400  # start y positon [m]
+    gx = 600  # goal x position [m]
+    gy = 100  # goal y position [m]
+    grid_size = 10  # potential grid size [m]
+    robot_radius = 10  # robot radius [m]
+
+    ox, oy = create_obsticles(mapOfWorld)
+
+    if show_animation:
+        plt.grid(True)
+        plt.axis("equal")
+
+    # path generation
+    _, _ = potential_field_planning(sx, sy, gx, gy, ox, oy, grid_size, robot_radius)
+
+    if show_animation:
+        plt.show()
+
+    print("X_Pos", px)
+    print("Y_Pos", py)  
+
+if __name__ == '__main__':
+    print(__file__ + " start!!")
+    main()
+    print(__file__ + " Done!!")
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/sphero.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/sphero.py
new file mode 100644
index 0000000..b5138d1
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/sphero.py
@@ -0,0 +1,22 @@
+import numpy as np
+def ref_winkel(sphero, soll):
+
+    startpunkt = sphero.positionsauslesen
+
+    sphero.roll(100,0)
+    sphero.wait(2)
+    sphero.roll(0,0)
+    sphero.wait(0.5)
+
+    ref =  sphero.positionsauslesen
+
+    sphero.wait(0.5)
+    sphero.roll(100,0)
+    sphero.wait(2)
+    sphero.roll(0,0)
+    
+    start_ref = ref-startpunkt
+    start_soll = soll-startpunkt
+    phi = np.arccos(start_ref*start_soll / (np.linalg.norm(start_ref)*np.linalg.norm(start_soll)))
+    return phi
+
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/test.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/test.py
new file mode 100644
index 0000000..b5c4cbb
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/test.py
@@ -0,0 +1,23 @@
+#Map erstellen
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+success, img = cap.read()
+
+gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+
+mask_list= np.ndarray.tolist(mask)
+
+for i in range(0,mask.shape[0]):
+    mapOfWorld[i] = ['W' if j > 200 else ' ' for j in mask_list[i]]
+
+print(mapOfWorld)
+
+
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/treiber.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/treiber.py
new file mode 100644
index 0000000..ec34350
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/treiber.py
@@ -0,0 +1,638 @@
+from bluepy.btle import Peripheral
+from bluepy import btle
+from sphero_mini_controller._constants import *
+import struct
+import time
+import sys
+
+class SpheroMini():
+    def __init__(self, MACAddr, verbosity = 4, user_delegate = None):
+        '''
+        initialize class instance and then build collect BLE sevices and characteristics.
+        Also sends text string to Anti-DOS characteristic to prevent returning to sleep,
+        and initializes notifications (which is what the sphero uses to send data back to
+        the client).
+        '''
+        self.verbosity = verbosity # 0 = Silent,
+                                   # 1 = Connection/disconnection only
+                                   # 2 = Init messages
+                                   # 3 = Recieved commands
+                                   # 4 = Acknowledgements
+        self.sequence = 1
+        self.v_batt = None # will be updated with battery voltage when sphero.getBatteryVoltage() is called
+        self.firmware_version = [] # will be updated with firware version when sphero.returnMainApplicationVersion() is called
+
+        if self.verbosity > 0:
+            print("[INFO] Connecting to ", MACAddr)
+        self.p = Peripheral(MACAddr, "random") #connect
+
+        if self.verbosity > 1:
+            print("[INIT] Initializing")
+
+        # Subscribe to notifications
+        self.sphero_delegate = MyDelegate(self, user_delegate) # Pass a reference to this instance when initializing
+        self.p.setDelegate(self.sphero_delegate)
+
+        if self.verbosity > 1:
+            print("[INIT] Read all characteristics and descriptors")
+        # Get characteristics and descriptors
+        self.API_V2_characteristic = self.p.getCharacteristics(uuid="00010002-574f-4f20-5370-6865726f2121")[0]
+        self.AntiDOS_characteristic = self.p.getCharacteristics(uuid="00020005-574f-4f20-5370-6865726f2121")[0]
+        self.DFU_characteristic = self.p.getCharacteristics(uuid="00020002-574f-4f20-5370-6865726f2121")[0]
+        self.DFU2_characteristic = self.p.getCharacteristics(uuid="00020004-574f-4f20-5370-6865726f2121")[0]
+        self.API_descriptor = self.API_V2_characteristic.getDescriptors(forUUID=0x2902)[0]
+        self.DFU_descriptor = self.DFU_characteristic.getDescriptors(forUUID=0x2902)[0]
+
+        # The rest of this sequence was observed during bluetooth sniffing:
+        # Unlock code: prevent the sphero mini from going to sleep again after 10 seconds
+        if self.verbosity > 1:
+            print("[INIT] Writing AntiDOS characteristic unlock code")
+        self.AntiDOS_characteristic.write("usetheforce...band".encode(), withResponse=True)
+
+        # Enable DFU notifications:
+        if self.verbosity > 1:
+            print("[INIT] Configuring DFU descriptor")
+        self.DFU_descriptor.write(struct.pack('<bb', 0x01, 0x00), withResponse = True)
+
+        # No idea what this is for. Possibly a device ID of sorts? Read request returns '00 00 09 00 0c 00 02 02':
+        if self.verbosity > 1:
+            print("[INIT] Reading DFU2 characteristic")
+        _ = self.DFU2_characteristic.read()
+
+        # Enable API notifications:
+        if self.verbosity > 1:
+            print("[INIT] Configuring API dectriptor")
+        self.API_descriptor.write(struct.pack('<bb', 0x01, 0x00), withResponse = True)
+
+        self.wake()
+
+        # Finished initializing:
+        if self.verbosity > 1:
+            print("[INIT] Initialization complete\n")
+
+    def disconnect(self):
+        if self.verbosity > 0:
+            print("[INFO] Disconnecting")
+        
+        self.p.disconnect()
+
+    def wake(self):
+        '''
+        Bring device out of sleep mode (can only be done if device was in sleep, not deep sleep).
+        If in deep sleep, the device should be connected to USB power to wake.
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Waking".format(self.sequence))
+        
+        self._send(characteristic=self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=powerCommandIDs["wake"],
+                   payload=[]) # empty payload
+
+        self.getAcknowledgement("Wake")
+
+    def sleep(self, deepSleep=False):
+        '''
+        Put device to sleep or deep sleep (deep sleep needs USB power connected to wake up)
+        '''
+        if deepSleep:
+            sleepCommID=powerCommandIDs["deepSleep"]
+            if self.verbosity > 0:
+                print("[INFO] Going into deep sleep. Connect USB power to wake.")
+        else:
+            sleepCommID=powerCommandIDs["sleep"]
+        self._send(characteristic=self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=sleepCommID,
+                   payload=[]) #empty payload
+
+    def setLEDColor(self, red = None, green = None, blue = None):
+        '''
+        Set device LED color based on RGB vales (each can  range between 0 and 0xFF)
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Setting main LED colour to [{}, {}, {}]".format(self.sequence, red, green, blue))
+        
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['userIO'], # 0x1a
+                  commID = userIOCommandIDs["allLEDs"], # 0x0e
+                  payload = [0x00, 0x0e, red, green, blue])
+
+        self.getAcknowledgement("LED/backlight")
+
+    def setBackLEDIntensity(self, brightness=None):
+        '''
+        Set device LED backlight intensity based on 0-255 values
+
+        NOTE: this is not the same as aiming - it only turns on the LED
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Setting backlight intensity to {}".format(self.sequence, brightness))
+
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['userIO'],
+                  commID = userIOCommandIDs["allLEDs"],
+                  payload = [0x00, 0x01, brightness])
+
+        self.getAcknowledgement("LED/backlight")
+
+    def roll(self, speed=None, heading=None):
+        '''
+        Start to move the Sphero at a given direction and speed.
+        heading: integer from 0 - 360 (degrees)
+        speed: Integer from 0 - 255
+
+        Note: the zero heading should be set at startup with the resetHeading method. Otherwise, it may
+        seem that the sphero doesn't honor the heading argument
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Rolling with speed {} and heading {}".format(self.sequence, speed, heading))
+    
+        if abs(speed) > 255:
+            print("WARNING: roll speed parameter outside of allowed range (-255 to +255)")
+
+        if speed < 0:
+            speed = -1*speed+256 # speed values > 256 in the send packet make the spero go in reverse
+
+        speedH = (speed & 0xFF00) >> 8
+        speedL = speed & 0xFF
+        headingH = (heading & 0xFF00) >> 8
+        headingL = heading & 0xFF
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['driving'],
+                  commID = drivingCommands["driveWithHeading"],
+                  payload = [speedL, headingH, headingL, speedH])
+
+        self.getAcknowledgement("Roll")
+
+    def resetHeading(self):
+        '''
+        Reset the heading zero angle to the current heading (useful during aiming)
+        Note: in order to manually rotate the sphero, you need to call stabilization(False).
+        Once the heading has been set, call stabilization(True).
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Resetting heading".format(self.sequence))
+    
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['driving'],
+                  commID = drivingCommands["resetHeading"],
+                  payload = []) #empty payload
+
+        self.getAcknowledgement("Heading")
+
+    def returnMainApplicationVersion(self):
+        '''
+        Sends command to return application data in a notification
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Requesting firmware version".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID = deviceID['systemInfo'],
+                   commID = SystemInfoCommands['mainApplicationVersion'],
+                   payload = []) # empty
+
+        self.getAcknowledgement("Firmware")
+
+    def getBatteryVoltage(self):
+        '''
+        Sends command to return battery voltage data in a notification.
+        Data printed to console screen by the handleNotifications() method in the MyDelegate class.
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Requesting battery voltage".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=powerCommandIDs['batteryVoltage'],
+                   payload=[]) # empty
+
+        self.getAcknowledgement("Battery")
+
+    def stabilization(self, stab = True):
+        '''
+        Sends command to turn on/off the motor stabilization system (required when manually turning/aiming the sphero)
+        '''
+        if stab == True:
+            if self.verbosity > 2:
+                    print("[SEND {}] Enabling stabilization".format(self.sequence))
+            val = 1
+        else:
+            if self.verbosity > 2:
+                    print("[SEND {}] Disabling stabilization".format(self.sequence))
+            val = 0
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['driving'],
+                   commID=drivingCommands['stabilization'],
+                   payload=[val])
+
+        self.getAcknowledgement("Stabilization")
+
+    def wait(self, delay):
+        '''
+        This is a non-blocking delay command. It is similar to time.sleep(), except it allows asynchronous 
+        notification handling to still be performed.
+        '''
+        start = time.time()
+        while(1):
+            self.p.waitForNotifications(0.001)
+            if time.time() - start > delay:
+                break
+
+    def _send(self, characteristic=None, devID=None, commID=None, payload=[]):
+        '''
+        A generic "send" method, which will be used by other methods to send a command ID, payload and
+        appropriate checksum to a specified device ID. Mainly useful because payloads are optional,
+        and can be of varying length, to convert packets to binary, and calculate and send the
+        checksum. For internal use only.
+
+        Packet structure has the following format (in order):
+
+        - Start byte: always 0x8D
+        - Flags byte: indicate response required, etc
+        - Virtual device ID: see _constants.py
+        - Command ID: see _constants.py
+        - Sequence number: Seems to be arbitrary. I suspect it is used to match commands to response packets (in which the number is echoed).
+        - Payload: Could be varying number of bytes (incl. none), depending on the command
+        - Checksum: See below for calculation
+        - End byte: always 0xD8
+
+        '''
+        sendBytes = [sendPacketConstants["StartOfPacket"],
+                    sum([flags["resetsInactivityTimeout"], flags["requestsResponse"]]),
+                    devID,
+                    commID,
+                    self.sequence] + payload # concatenate payload list
+
+        self.sequence += 1 # Increment sequence number, ensures we can identify response packets are for this command
+        if self.sequence > 255:
+            self.sequence = 0
+
+        # Compute and append checksum and add EOP byte:
+        # From Sphero docs: "The [checksum is the] modulo 256 sum of all the bytes
+        #                   from the device ID through the end of the data payload,
+        #                   bit inverted (1's complement)"
+        # For the sphero mini, the flag bits must be included too:
+        checksum = 0
+        for num in sendBytes[1:]:
+            checksum = (checksum + num) & 0xFF # bitwise "and to get modulo 256 sum of appropriate bytes
+        checksum = 0xff - checksum # bitwise 'not' to invert checksum bits
+        sendBytes += [checksum, sendPacketConstants["EndOfPacket"]] # concatenate
+
+        # Convert numbers to bytes
+        output = b"".join([x.to_bytes(1, byteorder='big') for x in sendBytes])
+
+        #send to specified characteristic:
+        characteristic.write(output, withResponse = True)
+
+    def getAcknowledgement(self, ack):
+        #wait up to 10 secs for correct acknowledgement to come in, including sequence number!
+        start = time.time()
+        while(1):
+            self.p.waitForNotifications(1)
+            if self.sphero_delegate.notification_seq == self.sequence-1: # use one less than sequence, because _send function increments it for next send. 
+                if self.verbosity > 3:
+                    print("[RESP {}] {}".format(self.sequence-1, self.sphero_delegate.notification_ack))
+                self.sphero_delegate.clear_notification()
+                break
+            elif self.sphero_delegate.notification_seq >= 0:
+                print("Unexpected ACK. Expected: {}/{}, received: {}/{}".format(
+                    ack, self.sequence, self.sphero_delegate.notification_ack.split()[0],
+                    self.sphero_delegate.notification_seq)
+                    )
+            if time.time() > start + 10:
+                print("Timeout waiting for acknowledgement: {}/{}".format(ack, self.sequence))
+                break
+
+# =======================================================================
+# The following functions are experimental:
+# =======================================================================
+
+    def configureCollisionDetection(self,
+                                     xThreshold = 50, 
+                                     yThreshold = 50, 
+                                     xSpeed = 50, 
+                                     ySpeed = 50, 
+                                     deadTime = 50, # in 10 millisecond increments
+                                     method = 0x01, # Must be 0x01        
+                                     callback = None):
+        '''
+        Appears to function the same as other Sphero models, however speed settings seem to have no effect. 
+        NOTE: Setting to zero seems to cause bluetooth errors with the Sphero Mini/bluepy library - set to 
+        255 to make it effectively disabled.
+
+        deadTime disables future collisions for a short period of time to avoid repeat triggering by the same
+        event. Set in 10ms increments. So if deadTime = 50, that means the delay will be 500ms, or half a second.
+        
+        From Sphero docs:
+        
+            xThreshold/yThreshold: An 8-bit settable threshold for the X (left/right) and Y (front/back) axes 
+            of Sphero.
+
+            xSpeed/ySpeed: An 8-bit settable speed value for the X and Y axes. This setting is ranged by the 
+            speed, then added to xThreshold, yThreshold to generate the final threshold value.
+        '''
+        
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring collision detection".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['configureCollision'],
+                   payload=[method, xThreshold, xSpeed, yThreshold, ySpeed, deadTime])
+
+        self.collision_detection_callback = callback
+
+        self.getAcknowledgement("Collision")
+
+    def configureSensorStream(self): # Use default values
+        '''
+        Send command to configure sensor stream using default values as found during bluetooth 
+        sniffing of the Sphero Edu app.
+
+        Must be called after calling configureSensorMask()
+        '''
+        bitfield1 = 0b00000000 # Unknown function - needs experimenting
+        bitfield2 = 0b00000000 # Unknown function - needs experimenting
+        bitfield3 = 0b00000000 # Unknown function - needs experimenting
+        bitfield4 = 0b00000000 # Unknown function - needs experimenting
+
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring sensor stream".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['configureSensorStream'],
+                   payload=[bitfield1, bitfield1, bitfield1, bitfield1])
+
+        self.getAcknowledgement("Sensor")
+
+    def configureSensorMask(self,
+                            sample_rate_divisor = 0x25, # Must be > 0
+                            packet_count = 0,
+                            IMU_pitch = False,
+                            IMU_roll = False,
+                            IMU_yaw = False,
+                            IMU_acc_x = False,
+                            IMU_acc_y = False,
+                            IMU_acc_z = False,
+                            IMU_gyro_x = False,
+                            IMU_gyro_y = False,
+                            IMU_gyro_z = False):
+
+        '''
+        Send command to configure sensor mask using default values as found during bluetooth 
+        sniffing of the Sphero Edu app. From experimentation, it seems that these are he functions of each:
+        
+        Sampling_rate_divisor. Slow data EG: Set to 0x32 to the divide data rate by 50. Setting below 25 (0x19) causes 
+                bluetooth errors        
+        
+        Packet_count: Select the number of packets to transmit before ending the stream. Set to zero to stream infinitely
+        
+        All IMU bool parameters: Toggle transmission of that value on or off (e.g. set IMU_acc_x = True to include the 
+                X-axis accelerometer readings in the sensor stream)
+        '''
+
+        # Construct bitfields based on function parameters:
+        IMU_bitfield1 = (IMU_pitch<<2) + (IMU_roll<<1) + IMU_yaw
+        IMU_bitfield2 = ((IMU_acc_y<<7) + (IMU_acc_z<<6) + (IMU_acc_x<<5) + \
+                         (IMU_gyro_y<<4) + (IMU_gyro_x<<2) + (IMU_gyro_z<<2))
+        
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring sensor mask".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensorMask'],
+                   payload=[0x00,               # Unknown param - altering it seems to slow data rate. Possibly averages multiple readings?
+                            sample_rate_divisor,       
+                            packet_count,       # Packet count: select the number of packets to stop streaming after (zero = infinite)
+                            0b00,               # Unknown param: seems to be another accelerometer bitfield? Z-acc, Y-acc
+                            IMU_bitfield1,
+                            IMU_bitfield2,
+                            0b00])              # reserved, Position?, Position?, velocity?, velocity?, Y-gyro, timer, reserved
+
+        self.getAcknowledgement("Mask")
+
+        '''
+        Since the sensor values arrive as unlabelled lists in the order that they appear in the bitfields above, we need 
+        to create a list of sensors that have been configured.Once we have this list, then in the default_delegate class, 
+        we can get sensor values as attributes of the sphero_mini class.
+        e.g. print(sphero.IMU_yaw) # displays the current yaw angle
+        '''
+
+        # Initialize dictionary with sensor names as keys and their bool values (set by the user) as values:
+        availableSensors = {"IMU_pitch" : IMU_pitch,
+                            "IMU_roll" : IMU_roll,
+                            "IMU_yaw" : IMU_yaw,
+                            "IMU_acc_y" : IMU_acc_y,
+                            "IMU_acc_z" : IMU_acc_z,
+                            "IMU_acc_x" : IMU_acc_x,
+                            "IMU_gyro_y" : IMU_gyro_y,
+                            "IMU_gyro_x" : IMU_gyro_x,
+                            "IMU_gyro_z" : IMU_gyro_z}
+        
+        # Create list of of only sensors that have been "activated" (set as true in the method arguments):
+        self.configured_sensors = [name for name in availableSensors if availableSensors[name] == True]
+
+    def sensor1(self): # Use default values
+        '''
+        Unknown function. Observed in bluetooth sniffing. 
+        '''
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensor1'],
+                   payload=[0x01])
+
+        self.getAcknowledgement("Sensor1")
+
+    def sensor2(self): # Use default values
+        '''
+        Unknown function. Observed in bluetooth sniffing. 
+        '''
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensor2'],
+                   payload=[0x00])
+
+        self.getAcknowledgement("Sensor2")
+
+# =======================================================================
+
+class MyDelegate(btle.DefaultDelegate):
+
+    '''
+    This class handles notifications (both responses and asynchronous notifications).
+    
+    Usage of this class is described in the Bluepy documentation
+    
+    '''
+
+    def __init__(self, sphero_class, user_delegate):
+        self.sphero_class = sphero_class # for saving sensor values as attributes of sphero class instance
+        self.user_delegate = user_delegate # to directly notify users of callbacks
+        btle.DefaultDelegate.__init__(self)
+        self.clear_notification()
+        self.notificationPacket = []
+
+    def clear_notification(self):
+        self.notification_ack = "DEFAULT ACK"
+        self.notification_seq = -1
+
+    def bits_to_num(self, bits):
+        '''
+        This helper function decodes bytes from sensor packets into single precision floats. Encoding follows the
+        the IEEE-754 standard.
+        '''
+        num = int(bits, 2).to_bytes(len(bits) // 8, byteorder='little')
+        num = struct.unpack('f', num)[0]
+        return num
+
+    def handleNotification(self, cHandle, data):
+        '''
+        This method acts as an interrupt service routine. When a notification comes in, this
+        method is invoked, with the variable 'cHandle' being the handle of the characteristic that
+        sent the notification, and 'data' being the payload (sent one byte at a time, so the packet
+        needs to be reconstructed)  
+
+        The method keeps appending bytes to the payload packet byte list until end-of-packet byte is
+        encountered. Note that this is an issue, because 0xD8 could be sent as part of the payload of,
+        say, the battery voltage notification. In future, a more sophisticated method will be required.
+        '''
+        # Allow the user to intercept and process data first..
+        if self.user_delegate != None:
+            if self.user_delegate.handleNotification(cHandle, data):
+                return
+        
+        #print("Received notification with packet ", str(data))
+
+        for data_byte in data: # parse each byte separately (sometimes they arrive simultaneously)
+
+            self.notificationPacket.append(data_byte) # Add new byte to packet list
+
+            # If end of packet (need to find a better way to segment the packets):
+            if data_byte == sendPacketConstants['EndOfPacket']:
+                # Once full the packet has arrived, parse it:
+                # Packet structure is similar to the outgoing send packets (see docstring in sphero_mini._send())
+                
+                # Attempt to unpack. Might fail if packet is too badly corrupted
+                try:
+                    start, flags_bits, devid, commcode, seq, *notification_payload, chsum, end = self.notificationPacket
+                except ValueError:
+                    print("Warning: notification packet unparseable ", self.notificationPacket)
+                    self.notificationPacket = [] # Discard this packet
+                    return # exit
+
+                # Compute and append checksum and add EOP byte:
+                # From Sphero docs: "The [checksum is the] modulo 256 sum of all the bytes
+                #                   from the device ID through the end of the data payload,
+                #                   bit inverted (1's complement)"
+                # For the sphero mini, the flag bits must be included too:
+                checksum_bytes = [flags_bits, devid, commcode, seq] + notification_payload
+                checksum = 0 # init
+                for num in checksum_bytes:
+                    checksum = (checksum + num) & 0xFF # bitwise "and to get modulo 256 sum of appropriate bytes
+                checksum = 0xff - checksum # bitwise 'not' to invert checksum bits
+                if checksum != chsum: # check computed checksum against that recieved in the packet
+                    print("Warning: notification packet checksum failed - ", str(self.notificationPacket))
+                    self.notificationPacket = [] # Discard this packet
+                    return # exit
+
+                # Check if response packet:
+                if flags_bits & flags['isResponse']: # it is a response
+
+                    # Use device ID and command code to determine which command is being acknowledged:
+                    if devid == deviceID['powerInfo'] and commcode == powerCommandIDs['wake']:
+                        self.notification_ack = "Wake acknowledged" # Acknowledgement after wake command
+                        
+                    elif devid == deviceID['driving'] and commcode == drivingCommands['driveWithHeading']:
+                        self.notification_ack = "Roll command acknowledged"
+
+                    elif devid == deviceID['driving'] and commcode == drivingCommands['stabilization']:
+                        self.notification_ack = "Stabilization command acknowledged"
+
+                    elif devid == deviceID['userIO'] and commcode == userIOCommandIDs['allLEDs']:
+                        self.notification_ack = "LED/backlight color command acknowledged"
+
+                    elif devid == deviceID['driving'] and commcode == drivingCommands["resetHeading"]:
+                        self.notification_ack = "Heading reset command acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["configureCollision"]:
+                        self.notification_ack = "Collision detection configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["configureSensorStream"]:
+                        self.notification_ack = "Sensor stream configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensorMask"]:
+                        self.notification_ack = "Mask configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensor1"]:
+                        self.notification_ack = "Sensor1 acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensor2"]:
+                        self.notification_ack = "Sensor2 acknowledged"
+
+                    elif devid == deviceID['powerInfo'] and commcode == powerCommandIDs['batteryVoltage']:
+                        V_batt = notification_payload[2] + notification_payload[1]*256 + notification_payload[0]*65536
+                        V_batt /= 100 # Notification gives V_batt in 10mV increments. Divide by 100 to get to volts.
+                        self.notification_ack = "Battery voltage:" + str(V_batt) + "v"
+                        self.sphero_class.v_batt = V_batt
+
+                    elif devid == deviceID['systemInfo'] and commcode == SystemInfoCommands['mainApplicationVersion']:
+                        version = '.'.join(str(x) for x in notification_payload)
+                        self.notification_ack = "Firmware version: " + version
+                        self.sphero_class.firmware_version = notification_payload
+                                                
+                    else:
+                        self.notification_ack = "Unknown acknowledgement" #print(self.notificationPacket)
+                        print(self.notificationPacket, "===================> Unknown ack packet")
+
+                    self.notification_seq = seq
+
+                else: # Not a response packet - therefore, asynchronous notification (e.g. collision detection, etc):
+                    
+                    # Collision detection:
+                    if devid == deviceID['sensor'] and commcode == sensorCommands['collisionDetectedAsync']:
+                        # The first four bytes are data that is still un-parsed. the remaining unsaved bytes are always zeros
+                        _, _, _, _, _, _, axis, _, Y_mag, _, X_mag, *_ = notification_payload
+                        if axis == 1: 
+                            dir = "Left/right"
+                        else:
+                            dir = 'Forward/back'
+                        print("Collision detected:")
+                        print("\tAxis: ", dir)
+                        print("\tX_mag: ", X_mag)
+                        print("\tY_mag: ", Y_mag)
+
+                        if self.sphero_class.collision_detection_callback is not None:
+                            self.notificationPacket = [] # need to clear packet, in case new notification comes in during callback
+                            self.sphero_class.collision_detection_callback()
+
+                    # Sensor response:
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands['sensorResponse']:
+                        # Convert to binary, pad bytes with leading zeros:
+                        val = ''
+                        for byte in notification_payload:
+                            val += format(int(bin(byte)[2:], 2), '#010b')[2:]
+                        
+                        # Break into 32-bit chunks
+                        nums = []
+                        while(len(val) > 0):
+                            num, val = val[:32], val[32:] # Slice off first 16 bits
+                            nums.append(num)
+                        
+                        # convert from raw bits to float:
+                        nums = [self.bits_to_num(num) for num in nums]
+
+                        # Set sensor values as class attributes:
+                        for name, value in zip(self.sphero_class.configured_sensors, nums):
+                            print("Setting sensor  at .", name, str(value))
+                            setattr(self.sphero_class, name, value)
+                        
+                    # Unrecognized packet structure:
+                    else:
+                        self.notification_ack = "Unknown asynchronous notification" #print(self.notificationPacket)
+                        print(str(self.notificationPacket) + " ===================> Unknown async packet")
+                        
+                self.notificationPacket = [] # Start new payload after this byte
\ No newline at end of file
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefront.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefront.py
new file mode 100644
index 0000000..1da3877
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefront.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+import time
+import sys
+       
+def newSearch(mapOfWorld, goal, start):
+    heap = []
+    newheap = []
+    x, y = goal
+    lastwave = 3
+    # Start out by marking nodes around G with a 3
+    moves = [(x + 1, y), (x - 1, y), (x, y - 1), (x, y + 1)]
+    
+    for move in moves:
+        if(mapOfWorld.positions[move] == ' '):
+            mapOfWorld.positions[move] = 3
+            heap.append(move)
+    for currentwave in range(4, 10000):
+        lastwave = lastwave + 1
+        while(heap != []):
+            position = heap.pop()
+            (x, y) = position
+            moves = [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]
+            #x, y = position
+            for move in moves:
+                if(mapOfWorld.positions[move] != 'W'):
+                    if(mapOfWorld.positions[move] == ' ' and mapOfWorld.positions[position] == currentwave - 1):
+                        mapOfWorld.positions[move] = currentwave
+                        newheap.append(move)
+                    if(move == start):
+                        return mapOfWorld, lastwave
+                    
+        #time.sleep(0.25)
+        #mapOfWorld.display()
+        #print heap
+        if(newheap == []):
+            print("Goal is unreachable")
+            return 1
+        heap = newheap
+        newheap = []
+          
+def printf(format, *args):
+    sys.stdout.write(format % args)    
+
+class Map(object):
+    
+    def __init__(self, xdim, ydim, positions):
+        self.xdim = xdim
+        self.ydim = ydim
+        self.positions = positions
+    def display(self):
+        printf("  ")
+        for i in range(self.ydim):
+            printf("%3s", str(i))
+        print
+        for x in range(self.xdim):
+            printf("%2s", str(x))
+            for y in range(self.ydim):
+                printf("%3s", str(self.positions[(x, y)]))
+            print
+    # Navigate though the number-populated maze
+    def nav(self, start, current):
+        self.pos = start
+        finished = False
+        
+        while(finished == False): # Run this code until we're at the goal
+            x, y = self.pos
+            self.positions[self.pos] = 'R' # Set the start on the map (this USUALLY keeps start the same)
+            #         SOUTH        NORTH         WEST      EAST
+            #           v           v             v          v      
+            moves = [(x + 1, y), (x - 1, y), (x, y - 1), (x, y + 1)] # Establish our directions
+            moveDirections = ["South", "North", "West", "East"] # Create a corresponding list of the cardinal directions
+            """ We don't want least to be 0, because then nothing would be less than it.
+                However, in order to make our code more robust, we set it to one of the values,
+                so that we're comparing least to an actual value instead of an arbitrary number (like 10).
+            """
+            # Do the actual comparing, and give us the least index so we know which move was the least
+            for w in range(len(moves)):
+                move = moves[w]
+                
+                # If the position has the current wave - 1 in it, move there.
+                if(self.positions[move] == current - 1):
+                    self.least = self.positions[move]
+                    leastIndex = w
+                # Or, if the position is the goal, stop the loop
+                elif(self.positions[move] == 'G'):
+                    finished = True
+                    leastIndex = w
+            # Decrement the current number so we can look for the next number
+            current = current - 1
+            self.positions[self.pos] = ' '
+            print( "Moved " + moveDirections[leastIndex])
+            self.pos = moves[leastIndex] # This will be converted to "move robot in x direction"
+            
+            #time.sleep(0.25)
+            #self.display()
+        # Change the goal position (or wherever we stop) to an "!" to show that we've arrived.
+        self.positions[self.pos] = '!'
+        self.display()
+# Find the goal, given the map
+def findGoal(mapOfWorld):
+    positions = mapOfWorld.positions
+    for x in range(mapOfWorld.xdim):
+        for y in range(mapOfWorld.ydim):
+            if(mapOfWorld.positions[(x, y)] == 'G'):
+                return (x, y)
+# Find the start, given the map
+def findStart(mapOfWorld):
+    positions = mapOfWorld.positions
+    for x in range(mapOfWorld.xdim):
+        for y in range(mapOfWorld.ydim):
+            if(mapOfWorld.positions[(x, y)] == 'R'):
+                
+                return (x, y)
+
+def convertMap(mapOfWorld):
+    positions = {}
+    xdim = len(mapOfWorld)
+    ydim = len(mapOfWorld[1])
+    for y in range(ydim):
+        for x in range(xdim):
+            positions[(x, y)] = mapOfWorld[x][y]
+            
+    return Map(xdim, ydim, positions)
+
+# Map erstellen
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+success, img = cap.read()
+
+gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+
+mask_list= np.ndarray.tolist(mask)
+
+for i in range(0,mask.shape[0]):
+    mapOfWorld[i] = ['W' if j > 200 else ' ' for j in mask_list[i]]
+
+mapOfWorld[200][200] = 'R' #Start Pos
+mapOfWorld[300][300] = 'G' #Ziel Pos
+
+print(mapOfWorld[200][200])
+print(mapOfWorld[300][300])
+
+mapOfLand = convertMap(mapOfWorld)
+mapOfLand.display()
+mapOfLand, lastwave = newSearch(mapOfLand, findGoal(mapOfLand), findStart(mapOfLand))
+mapOfLand.nav(findStart(mapOfLand), lastwave)
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefront_coverage_path_planner.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefront_coverage_path_planner.py
new file mode 100644
index 0000000..8586140
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefront_coverage_path_planner.py
@@ -0,0 +1,218 @@
+"""
+Distance/Path Transform Wavefront Coverage Path Planner
+
+author: Todd Tang
+paper: Planning paths of complete coverage of an unstructured environment
+         by a mobile robot - Zelinsky et.al.
+link: http://pinkwink.kr/attachment/cfile3.uf@1354654A4E8945BD13FE77.pdf
+"""
+
+import os
+import sys
+
+import matplotlib.pyplot as plt
+import numpy as np
+from scipy import ndimage
+
+do_animation = True
+
+
+def transform(
+        grid_map, src, distance_type='chessboard',
+        transform_type='path', alpha=0.01
+):
+    """transform
+
+    calculating transform of transform_type from src
+    in given distance_type
+
+    :param grid_map: 2d binary map
+    :param src: distance transform source
+    :param distance_type: type of distance used
+    :param transform_type: type of transform used
+    :param alpha: weight of Obstacle Transform used when using path_transform
+    """
+
+    n_rows, n_cols = grid_map.shape
+
+    if n_rows == 0 or n_cols == 0:
+        sys.exit('Empty grid_map.')
+
+    inc_order = [[0, 1], [1, 1], [1, 0], [1, -1],
+                 [0, -1], [-1, -1], [-1, 0], [-1, 1]]
+    if distance_type == 'chessboard':
+        cost = [1, 1, 1, 1, 1, 1, 1, 1]
+    elif distance_type == 'eculidean':
+        cost = [1, np.sqrt(2), 1, np.sqrt(2), 1, np.sqrt(2), 1, np.sqrt(2)]
+    else:
+        sys.exit('Unsupported distance type.')
+
+    transform_matrix = float('inf') * np.ones_like(grid_map, dtype=float)
+    transform_matrix[src[0], src[1]] = 0
+    if transform_type == 'distance':
+        eT = np.zeros_like(grid_map)
+    elif transform_type == 'path':
+        eT = ndimage.distance_transform_cdt(1 - grid_map, distance_type)
+    else:
+        sys.exit('Unsupported transform type.')
+
+    # set obstacle transform_matrix value to infinity
+    for i in range(n_rows):
+        for j in range(n_cols):
+            if grid_map[i][j] == 1.0:
+                transform_matrix[i][j] = float('inf')
+    is_visited = np.zeros_like(transform_matrix, dtype=bool)
+    is_visited[src[0], src[1]] = True
+    traversal_queue = [src]
+    calculated = [(src[0] - 1) * n_cols + src[1]]
+
+    def is_valid_neighbor(g_i, g_j):
+        return 0 <= g_i < n_rows and 0 <= g_j < n_cols \
+               and not grid_map[g_i][g_j]
+
+    while traversal_queue:
+        i, j = traversal_queue.pop(0)
+        for k, inc in enumerate(inc_order):
+            ni = i + inc[0]
+            nj = j + inc[1]
+            if is_valid_neighbor(ni, nj):
+                is_visited[i][j] = True
+
+                # update transform_matrix
+                transform_matrix[i][j] = min(
+                    transform_matrix[i][j],
+                    transform_matrix[ni][nj] + cost[k] + alpha * eT[ni][nj])
+
+                if not is_visited[ni][nj] \
+                        and ((ni - 1) * n_cols + nj) not in calculated:
+                    traversal_queue.append((ni, nj))
+                    calculated.append((ni - 1) * n_cols + nj)
+
+    return transform_matrix
+
+
+def get_search_order_increment(start, goal):
+    if start[0] >= goal[0] and start[1] >= goal[1]:
+        order = [[1, 0], [0, 1], [-1, 0], [0, -1],
+                 [1, 1], [1, -1], [-1, 1], [-1, -1]]
+    elif start[0] <= goal[0] and start[1] >= goal[1]:
+        order = [[-1, 0], [0, 1], [1, 0], [0, -1],
+                 [-1, 1], [-1, -1], [1, 1], [1, -1]]
+    elif start[0] >= goal[0] and start[1] <= goal[1]:
+        order = [[1, 0], [0, -1], [-1, 0], [0, 1],
+                 [1, -1], [-1, -1], [1, 1], [-1, 1]]
+    elif start[0] <= goal[0] and start[1] <= goal[1]:
+        order = [[-1, 0], [0, -1], [0, 1], [1, 0],
+                 [-1, -1], [-1, 1], [1, -1], [1, 1]]
+    else:
+        sys.exit('get_search_order_increment: cannot determine \
+            start=>goal increment order')
+    return order
+
+
+def wavefront(transform_matrix, start, goal):
+    """wavefront
+
+    performing wavefront coverage path planning
+
+    :param transform_matrix: the transform matrix
+    :param start: start point of planning
+    :param goal: goal point of planning
+    """
+
+    path = []
+    n_rows, n_cols = transform_matrix.shape
+
+    def is_valid_neighbor(g_i, g_j):
+        is_i_valid_bounded = 0 <= g_i < n_rows
+        is_j_valid_bounded = 0 <= g_j < n_cols
+        if is_i_valid_bounded and is_j_valid_bounded:
+            return not is_visited[g_i][g_j] and \
+                   transform_matrix[g_i][g_j] != float('inf')
+        return False
+
+    inc_order = get_search_order_increment(start, goal)
+
+    current_node = start
+    is_visited = np.zeros_like(transform_matrix, dtype=bool)
+
+    while current_node != goal:
+        i, j = current_node
+        path.append((i, j))
+        is_visited[i][j] = True
+
+        max_T = float('-inf')
+        i_max = (-1, -1)
+        i_last = 0
+        for i_last in range(len(path)):
+            current_node = path[-1 - i_last]  # get latest node in path
+            for ci, cj in inc_order:
+                ni, nj = current_node[0] + ci, current_node[1] + cj
+                if is_valid_neighbor(ni, nj) and \
+                        transform_matrix[ni][nj] > max_T:
+                    i_max = (ni, nj)
+                    max_T = transform_matrix[ni][nj]
+
+            if i_max != (-1, -1):
+                break
+
+        if i_max == (-1, -1):
+            break
+        else:
+            current_node = i_max
+            if i_last != 0:
+                print('backtracing to', current_node)
+    path.append(goal)
+
+    return path
+
+
+def visualize_path(grid_map, start, goal, path):  # pragma: no cover
+    oy, ox = start
+    gy, gx = goal
+    px, py = np.transpose(np.flipud(np.fliplr(path)))
+
+    if not do_animation:
+        plt.imshow(grid_map, cmap='Greys')
+        plt.plot(ox, oy, "-xy")
+        plt.plot(px, py, "-r")
+        plt.plot(gx, gy, "-pg")
+        plt.show()
+    else:
+        for ipx, ipy in zip(px, py):
+            plt.cla()
+            # for stopping simulation with the esc key.
+            plt.gcf().canvas.mpl_connect(
+                'key_release_event',
+                lambda event: [exit(0) if event.key == 'escape' else None])
+            plt.imshow(grid_map, cmap='Greys')
+            plt.plot(ox, oy, "-xb")
+            plt.plot(px, py, "-r")
+            plt.plot(gx, gy, "-pg")
+            plt.plot(ipx, ipy, "or")
+            plt.axis("equal")
+            plt.grid(True)
+            plt.pause(0.1)
+
+
+def main():
+    dir_path = os.path.dirname(os.path.realpath(__file__))
+    img = plt.imread(os.path.join(dir_path, 'map', 'test_2.png'))
+    img = 1 - img  # revert pixel values
+
+    start = (43, 0)
+    goal = (0, 0)
+
+    # distance transform wavefront
+    DT = transform(img, goal, transform_type='distance')
+    DT_path = wavefront(DT, start, goal)
+    visualize_path(img, start, goal, DT_path)
+
+    # path transform wavefront
+    PT = transform(img, goal, transform_type='path', alpha=0.01)
+    PT_path = wavefront(PT, start, goal)
+    visualize_path(img, start, goal, PT_path)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefrontgpt2.py b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefrontgpt2.py
new file mode 100644
index 0000000..ef76c9f
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/wavefrontgpt2.py
@@ -0,0 +1,76 @@
+from queue import Queue
+
+def wavefront_planner(map_array, start_pos, goal_pos):
+    rows = len(map_array)
+    cols = len(map_array[0])
+
+    # Überprüfe, ob Start- und Zielposition innerhalb der Karte liegen
+    if (start_pos[0] < 0 or start_pos[0] >= rows or start_pos[1] < 0 or start_pos[1] >= cols or
+            goal_pos[0] < 0 or goal_pos[0] >= rows or goal_pos[1] < 0 or goal_pos[1] >= cols):
+        raise ValueError("Start or goal position is out of bounds.")
+
+    # Erzeuge eine Kopie der Karte für den Wavefront-Algorithmus
+    wavefront_map = [[-1] * cols for _ in range(rows)]
+
+    # Definiere die Bewegungsrichtungen (4-Wege-Bewegung: oben, unten, links, rechts)
+    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
+
+    # Erzeuge eine Warteschlange für die Wellenfrontausbreitung
+    queue = Queue()
+    queue.put(goal_pos)
+
+    # Führe die Wellenfrontausbreitung durch
+    wavefront_map[goal_pos[0]][goal_pos[1]] = 0
+    while not queue.empty():
+        current_pos = queue.get()
+
+        # Überprüfe die Nachbarzellen
+        for direction in directions:
+            new_pos = (current_pos[0] + direction[0], current_pos[1] + direction[1])
+
+            # Überprüfe, ob die Nachbarzelle gültig und noch nicht besucht ist
+            if (0 <= new_pos[0] < rows and 0 <= new_pos[1] < cols and
+                    wavefront_map[new_pos[0]][new_pos[1]] == -1 and map_array[new_pos[0]][new_pos[1]] == 0):
+                wavefront_map[new_pos[0]][new_pos[1]] = wavefront_map[current_pos[0]][current_pos[1]] + 1
+                queue.put(new_pos)
+
+    # Überprüfe, ob der Startpunkt erreichbar ist
+    if wavefront_map[start_pos[0]][start_pos[1]] == -1:
+        raise ValueError("Start position is unreachable.")
+
+    # Verfolge den Pfad basierend auf der Wellenfront
+    path = [start_pos]
+    current_pos = start_pos
+    while current_pos != goal_pos:
+        next_pos = None
+        min_distance = float('inf')
+
+        for direction in directions:
+            neighbor_pos = (current_pos[0] + direction[0], current_pos[1] + direction[1])
+
+            if (0 <= neighbor_pos[0] < rows and 0 <= neighbor_pos[1] < cols and
+                    wavefront_map[neighbor_pos[0]][neighbor_pos[1]] < min_distance):
+                next_pos = neighbor_pos
+                min_distance = wavefront_map[neighbor_pos[0]][neighbor_pos[1]]
+
+        if next_pos is None:
+            raise ValueError("No path found.")
+
+        path.append(next_pos)
+        current_pos = next_pos
+
+    return path
+
+# Beispielverwendung
+map_array = [
+    [0, 0, 0, 0],
+    [0, 1, 1, 0],
+    [0, 0, 0, 0],
+    [0, 1, 1, 0],
+]
+
+start_pos = (0, 0)
+goal_pos = (1, 3)
+
+path = wavefront_planner(map_array, start_pos, goal_pos)
+print("Path:", path)
diff --git a/ros2_ws/build/sphero_mini_controller/colcon_build.rc b/ros2_ws/build/sphero_mini_controller/colcon_build.rc
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/colcon_build.rc
@@ -0,0 +1 @@
+0
diff --git a/ros2_ws/build/sphero_mini_controller/colcon_command_prefix_setup_py.sh b/ros2_ws/build/sphero_mini_controller/colcon_command_prefix_setup_py.sh
new file mode 100644
index 0000000..f9867d5
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/colcon_command_prefix_setup_py.sh
@@ -0,0 +1 @@
+# generated from colcon_core/shell/template/command_prefix.sh.em
diff --git a/ros2_ws/build/sphero_mini_controller/colcon_command_prefix_setup_py.sh.env b/ros2_ws/build/sphero_mini_controller/colcon_command_prefix_setup_py.sh.env
new file mode 100644
index 0000000..0e1cc2a
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/colcon_command_prefix_setup_py.sh.env
@@ -0,0 +1,61 @@
+AMENT_PREFIX_PATH=/opt/ros/humble
+COLCON=1
+COLORTERM=truecolor
+DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/999/bus
+DESKTOP_SESSION=ubuntu
+DISPLAY=:0
+GDMSESSION=ubuntu
+GNOME_DESKTOP_SESSION_ID=this-is-deprecated
+GNOME_SHELL_SESSION_MODE=ubuntu
+GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/211b2ac6_0a43_44d5_b3bf_a0e22ff3787d
+GNOME_TERMINAL_SERVICE=:1.128
+GPG_AGENT_INFO=/run/user/999/gnupg/S.gpg-agent:0:1
+GTK_MODULES=gail:atk-bridge
+HOME=/home/ubuntu
+IM_CONFIG_PHASE=1
+LANG=de_DE.UTF-8
+LANGUAGE=de_DE:en
+LC_ADDRESS=de_DE.UTF-8
+LC_IDENTIFICATION=de_DE.UTF-8
+LC_MEASUREMENT=de_DE.UTF-8
+LC_MONETARY=de_DE.UTF-8
+LC_NAME=de_DE.UTF-8
+LC_NUMERIC=de_DE.UTF-8
+LC_PAPER=de_DE.UTF-8
+LC_TELEPHONE=de_DE.UTF-8
+LC_TIME=de_DE.UTF-8
+LD_LIBRARY_PATH=/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/x86_64-linux-gnu:/opt/ros/humble/lib
+LOGNAME=ubuntu
+OLDPWD=/home/ubuntu
+PAPERSIZE=a4
+PATH=/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
+PWD=/home/ubuntu/ros2_ws/build/sphero_mini_controller
+PYTHONPATH=/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages
+QT_ACCESSIBILITY=1
+QT_IM_MODULE=ibus
+ROS_DISTRO=humble
+ROS_LOCALHOST_ONLY=0
+ROS_PYTHON_VERSION=3
+ROS_VERSION=2
+SESSION_MANAGER=local/ubuntu:@/tmp/.ICE-unix/2661,unix/ubuntu:/tmp/.ICE-unix/2661
+SHELL=/bin/bash
+SHLVL=1
+SSH_AGENT_LAUNCHER=gnome-keyring
+SSH_AUTH_SOCK=/run/user/999/keyring/ssh
+SYSTEMD_EXEC_PID=2684
+TERM=xterm-256color
+USER=ubuntu
+USERNAME=ubuntu
+VTE_VERSION=6800
+WINDOWPATH=2
+XAUTHORITY=/run/user/999/gdm/Xauthority
+XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
+XDG_CURRENT_DESKTOP=ubuntu:GNOME
+XDG_DATA_DIRS=/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
+XDG_MENU_PREFIX=gnome-
+XDG_RUNTIME_DIR=/run/user/999
+XDG_SESSION_CLASS=user
+XDG_SESSION_DESKTOP=ubuntu
+XDG_SESSION_TYPE=x11
+XMODIFIERS=@im=ibus
+_=/usr/bin/colcon
diff --git a/ros2_ws/build/sphero_mini_controller/install.log b/ros2_ws/build/sphero_mini_controller/install.log
new file mode 100644
index 0000000..0881f1a
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/install.log
@@ -0,0 +1,22 @@
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__init__.py
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontPlanner.py
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/treiber.py
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/_constants.py
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/blobErkennung.py
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node.cpython-310.pyc
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/__init__.cpython-310.pyc
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/WavefrontPlanner.cpython-310.pyc
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/treiber.cpython-310.pyc
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/_constants.cpython-310.pyc
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/blobErkennung.cpython-310.pyc
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/ament_index/resource_index/packages/sphero_mini_controller
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.xml
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/entry_points.txt
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/top_level.txt
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/zip-safe
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/PKG-INFO
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/SOURCES.txt
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/requires.txt
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/dependency_links.txt
+/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/sphero_mini
diff --git a/ros2_ws/build/sphero_mini_controller/prefix_override/__pycache__/sitecustomize.cpython-310.pyc b/ros2_ws/build/sphero_mini_controller/prefix_override/__pycache__/sitecustomize.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2bd0054d0a2debc06129b0ef052f83ce7d0b4c8f
GIT binary patch
literal 301
zcmd1j<>g{vU|>+awmPMjfq~&Mh=Yuo85kHG7#J9e6&M&8QW#Pga~Pr+QW>%sQyJo!
zQkYm6QW@ewY~~ckU<OU*mms}<RmS=m`MIh3rAeiEC8hdB`Nc-@<;D7$dBr7(IXU{p
z1sSPD`SH1#d71Ia`FSNp`8heMMVc(Pn2RfmZ?P2=rKV+8+~O`uP0WdhaZ)Q%lcAiI
z3`J}V3=ra15LTO#N;7j(aM+^{F)}{CEVZa8GbL5OII|=*xwN<>KR2@~Rj;7(7Kcr4
VeoARhsvRT9;~={@7&sUO7y-I#S<3(b

literal 0
HcmV?d00001

diff --git a/ros2_ws/build/sphero_mini_controller/prefix_override/sitecustomize.py b/ros2_ws/build/sphero_mini_controller/prefix_override/sitecustomize.py
new file mode 100644
index 0000000..231b97a
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/prefix_override/sitecustomize.py
@@ -0,0 +1,3 @@
+import sys
+sys.real_prefix = sys.prefix
+sys.prefix = sys.exec_prefix = '/home/ubuntu/ros2_ws/install/sphero_mini_controller'
diff --git a/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO
new file mode 100644
index 0000000..1772b2b
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO
@@ -0,0 +1,12 @@
+Metadata-Version: 2.1
+Name: sphero-mini-controller
+Version: 0.0.0
+Summary: TODO: Package description
+Home-page: UNKNOWN
+Maintainer: ubuntu
+Maintainer-email: ubuntu@todo.todo
+License: TODO: License declaration
+Platform: UNKNOWN
+
+UNKNOWN
+
diff --git a/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt
new file mode 100644
index 0000000..450bb51
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt
@@ -0,0 +1,20 @@
+package.xml
+setup.cfg
+setup.py
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/zip-safe
+resource/sphero_mini_controller
+sphero_mini_controller/WavefrontPlanner.py
+sphero_mini_controller/__init__.py
+sphero_mini_controller/_constants.py
+sphero_mini_controller/blobErkennung.py
+sphero_mini_controller/my_first_node.py
+sphero_mini_controller/treiber.py
+test/test_copyright.py
+test/test_flake8.py
+test/test_pep257.py
\ No newline at end of file
diff --git a/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt
new file mode 100644
index 0000000..6a40ae6
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt
@@ -0,0 +1,3 @@
+[console_scripts]
+sphero_mini = sphero_mini_controller.my_first_node:main
+
diff --git a/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt
new file mode 100644
index 0000000..49fe098
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt
@@ -0,0 +1 @@
+setuptools
diff --git a/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt
new file mode 100644
index 0000000..60845da
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt
@@ -0,0 +1 @@
+sphero_mini_controller
diff --git a/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/zip-safe b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ros2_ws/build/sphero_mini_controller/sphero_mini_controller.egg-info/zip-safe
@@ -0,0 +1 @@
+
diff --git a/ros2_ws/install/.colcon_install_layout b/ros2_ws/install/.colcon_install_layout
new file mode 100644
index 0000000..3aad533
--- /dev/null
+++ b/ros2_ws/install/.colcon_install_layout
@@ -0,0 +1 @@
+isolated
diff --git a/ros2_ws/install/COLCON_IGNORE b/ros2_ws/install/COLCON_IGNORE
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/install/_local_setup_util_ps1.py b/ros2_ws/install/_local_setup_util_ps1.py
new file mode 100644
index 0000000..98348ee
--- /dev/null
+++ b/ros2_ws/install/_local_setup_util_ps1.py
@@ -0,0 +1,404 @@
+# Copyright 2016-2019 Dirk Thomas
+# Licensed under the Apache License, Version 2.0
+
+import argparse
+from collections import OrderedDict
+import os
+from pathlib import Path
+import sys
+
+
+FORMAT_STR_COMMENT_LINE = '# {comment}'
+FORMAT_STR_SET_ENV_VAR = 'Set-Item -Path "Env:{name}" -Value "{value}"'
+FORMAT_STR_USE_ENV_VAR = '$env:{name}'
+FORMAT_STR_INVOKE_SCRIPT = '_colcon_prefix_powershell_source_script "{script_path}"'
+FORMAT_STR_REMOVE_LEADING_SEPARATOR = ''
+FORMAT_STR_REMOVE_TRAILING_SEPARATOR = ''
+
+DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate'
+DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate'
+DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists'
+DSV_TYPE_SET = 'set'
+DSV_TYPE_SET_IF_UNSET = 'set-if-unset'
+DSV_TYPE_SOURCE = 'source'
+
+
+def main(argv=sys.argv[1:]):  # noqa: D103
+    parser = argparse.ArgumentParser(
+        description='Output shell commands for the packages in topological '
+                    'order')
+    parser.add_argument(
+        'primary_extension',
+        help='The file extension of the primary shell')
+    parser.add_argument(
+        'additional_extension', nargs='?',
+        help='The additional file extension to be considered')
+    parser.add_argument(
+        '--merged-install', action='store_true',
+        help='All install prefixes are merged into a single location')
+    args = parser.parse_args(argv)
+
+    packages = get_packages(Path(__file__).parent, args.merged_install)
+
+    ordered_packages = order_packages(packages)
+    for pkg_name in ordered_packages:
+        if _include_comments():
+            print(
+                FORMAT_STR_COMMENT_LINE.format_map(
+                    {'comment': 'Package: ' + pkg_name}))
+        prefix = os.path.abspath(os.path.dirname(__file__))
+        if not args.merged_install:
+            prefix = os.path.join(prefix, pkg_name)
+        for line in get_commands(
+            pkg_name, prefix, args.primary_extension,
+            args.additional_extension
+        ):
+            print(line)
+
+    for line in _remove_ending_separators():
+        print(line)
+
+
+def get_packages(prefix_path, merged_install):
+    """
+    Find packages based on colcon-specific files created during installation.
+
+    :param Path prefix_path: The install prefix path of all packages
+    :param bool merged_install: The flag if the packages are all installed
+      directly in the prefix or if each package is installed in a subdirectory
+      named after the package
+    :returns: A mapping from the package name to the set of runtime
+      dependencies
+    :rtype: dict
+    """
+    packages = {}
+    # since importing colcon_core isn't feasible here the following constant
+    # must match colcon_core.location.get_relative_package_index_path()
+    subdirectory = 'share/colcon-core/packages'
+    if merged_install:
+        # return if workspace is empty
+        if not (prefix_path / subdirectory).is_dir():
+            return packages
+        # find all files in the subdirectory
+        for p in (prefix_path / subdirectory).iterdir():
+            if not p.is_file():
+                continue
+            if p.name.startswith('.'):
+                continue
+            add_package_runtime_dependencies(p, packages)
+    else:
+        # for each subdirectory look for the package specific file
+        for p in prefix_path.iterdir():
+            if not p.is_dir():
+                continue
+            if p.name.startswith('.'):
+                continue
+            p = p / subdirectory / p.name
+            if p.is_file():
+                add_package_runtime_dependencies(p, packages)
+
+    # remove unknown dependencies
+    pkg_names = set(packages.keys())
+    for k in packages.keys():
+        packages[k] = {d for d in packages[k] if d in pkg_names}
+
+    return packages
+
+
+def add_package_runtime_dependencies(path, packages):
+    """
+    Check the path and if it exists extract the packages runtime dependencies.
+
+    :param Path path: The resource file containing the runtime dependencies
+    :param dict packages: A mapping from package names to the sets of runtime
+      dependencies to add to
+    """
+    content = path.read_text()
+    dependencies = set(content.split(os.pathsep) if content else [])
+    packages[path.name] = dependencies
+
+
+def order_packages(packages):
+    """
+    Order packages topologically.
+
+    :param dict packages: A mapping from package name to the set of runtime
+      dependencies
+    :returns: The package names
+    :rtype: list
+    """
+    # select packages with no dependencies in alphabetical order
+    to_be_ordered = list(packages.keys())
+    ordered = []
+    while to_be_ordered:
+        pkg_names_without_deps = [
+            name for name in to_be_ordered if not packages[name]]
+        if not pkg_names_without_deps:
+            reduce_cycle_set(packages)
+            raise RuntimeError(
+                'Circular dependency between: ' + ', '.join(sorted(packages)))
+        pkg_names_without_deps.sort()
+        pkg_name = pkg_names_without_deps[0]
+        to_be_ordered.remove(pkg_name)
+        ordered.append(pkg_name)
+        # remove item from dependency lists
+        for k in list(packages.keys()):
+            if pkg_name in packages[k]:
+                packages[k].remove(pkg_name)
+    return ordered
+
+
+def reduce_cycle_set(packages):
+    """
+    Reduce the set of packages to the ones part of the circular dependency.
+
+    :param dict packages: A mapping from package name to the set of runtime
+      dependencies which is modified in place
+    """
+    last_depended = None
+    while len(packages) > 0:
+        # get all remaining dependencies
+        depended = set()
+        for pkg_name, dependencies in packages.items():
+            depended = depended.union(dependencies)
+        # remove all packages which are not dependent on
+        for name in list(packages.keys()):
+            if name not in depended:
+                del packages[name]
+        if last_depended:
+            # if remaining packages haven't changed return them
+            if last_depended == depended:
+                return packages.keys()
+        # otherwise reduce again
+        last_depended = depended
+
+
+def _include_comments():
+    # skipping comment lines when COLCON_TRACE is not set speeds up the
+    # processing especially on Windows
+    return bool(os.environ.get('COLCON_TRACE'))
+
+
+def get_commands(pkg_name, prefix, primary_extension, additional_extension):
+    commands = []
+    package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv')
+    if os.path.exists(package_dsv_path):
+        commands += process_dsv_file(
+            package_dsv_path, prefix, primary_extension, additional_extension)
+    return commands
+
+
+def process_dsv_file(
+    dsv_path, prefix, primary_extension=None, additional_extension=None
+):
+    commands = []
+    if _include_comments():
+        commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path}))
+    with open(dsv_path, 'r') as h:
+        content = h.read()
+    lines = content.splitlines()
+
+    basenames = OrderedDict()
+    for i, line in enumerate(lines):
+        # skip over empty or whitespace-only lines
+        if not line.strip():
+            continue
+        try:
+            type_, remainder = line.split(';', 1)
+        except ValueError:
+            raise RuntimeError(
+                "Line %d in '%s' doesn't contain a semicolon separating the "
+                'type from the arguments' % (i + 1, dsv_path))
+        if type_ != DSV_TYPE_SOURCE:
+            # handle non-source lines
+            try:
+                commands += handle_dsv_types_except_source(
+                    type_, remainder, prefix)
+            except RuntimeError as e:
+                raise RuntimeError(
+                    "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e
+        else:
+            # group remaining source lines by basename
+            path_without_ext, ext = os.path.splitext(remainder)
+            if path_without_ext not in basenames:
+                basenames[path_without_ext] = set()
+            assert ext.startswith('.')
+            ext = ext[1:]
+            if ext in (primary_extension, additional_extension):
+                basenames[path_without_ext].add(ext)
+
+    # add the dsv extension to each basename if the file exists
+    for basename, extensions in basenames.items():
+        if not os.path.isabs(basename):
+            basename = os.path.join(prefix, basename)
+        if os.path.exists(basename + '.dsv'):
+            extensions.add('dsv')
+
+    for basename, extensions in basenames.items():
+        if not os.path.isabs(basename):
+            basename = os.path.join(prefix, basename)
+        if 'dsv' in extensions:
+            # process dsv files recursively
+            commands += process_dsv_file(
+                basename + '.dsv', prefix, primary_extension=primary_extension,
+                additional_extension=additional_extension)
+        elif primary_extension in extensions and len(extensions) == 1:
+            # source primary-only files
+            commands += [
+                FORMAT_STR_INVOKE_SCRIPT.format_map({
+                    'prefix': prefix,
+                    'script_path': basename + '.' + primary_extension})]
+        elif additional_extension in extensions:
+            # source non-primary files
+            commands += [
+                FORMAT_STR_INVOKE_SCRIPT.format_map({
+                    'prefix': prefix,
+                    'script_path': basename + '.' + additional_extension})]
+
+    return commands
+
+
+def handle_dsv_types_except_source(type_, remainder, prefix):
+    commands = []
+    if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET):
+        try:
+            env_name, value = remainder.split(';', 1)
+        except ValueError:
+            raise RuntimeError(
+                "doesn't contain a semicolon separating the environment name "
+                'from the value')
+        try_prefixed_value = os.path.join(prefix, value) if value else prefix
+        if os.path.exists(try_prefixed_value):
+            value = try_prefixed_value
+        if type_ == DSV_TYPE_SET:
+            commands += _set(env_name, value)
+        elif type_ == DSV_TYPE_SET_IF_UNSET:
+            commands += _set_if_unset(env_name, value)
+        else:
+            assert False
+    elif type_ in (
+        DSV_TYPE_APPEND_NON_DUPLICATE,
+        DSV_TYPE_PREPEND_NON_DUPLICATE,
+        DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS
+    ):
+        try:
+            env_name_and_values = remainder.split(';')
+        except ValueError:
+            raise RuntimeError(
+                "doesn't contain a semicolon separating the environment name "
+                'from the values')
+        env_name = env_name_and_values[0]
+        values = env_name_and_values[1:]
+        for value in values:
+            if not value:
+                value = prefix
+            elif not os.path.isabs(value):
+                value = os.path.join(prefix, value)
+            if (
+                type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and
+                not os.path.exists(value)
+            ):
+                comment = f'skip extending {env_name} with not existing ' \
+                    f'path: {value}'
+                if _include_comments():
+                    commands.append(
+                        FORMAT_STR_COMMENT_LINE.format_map({'comment': comment}))
+            elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE:
+                commands += _append_unique_value(env_name, value)
+            else:
+                commands += _prepend_unique_value(env_name, value)
+    else:
+        raise RuntimeError(
+            'contains an unknown environment hook type: ' + type_)
+    return commands
+
+
+env_state = {}
+
+
+def _append_unique_value(name, value):
+    global env_state
+    if name not in env_state:
+        if os.environ.get(name):
+            env_state[name] = set(os.environ[name].split(os.pathsep))
+        else:
+            env_state[name] = set()
+    # append even if the variable has not been set yet, in case a shell script sets the
+    # same variable without the knowledge of this Python script.
+    # later _remove_ending_separators() will cleanup any unintentional leading separator
+    extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': extend + value})
+    if value not in env_state[name]:
+        env_state[name].add(value)
+    else:
+        if not _include_comments():
+            return []
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+def _prepend_unique_value(name, value):
+    global env_state
+    if name not in env_state:
+        if os.environ.get(name):
+            env_state[name] = set(os.environ[name].split(os.pathsep))
+        else:
+            env_state[name] = set()
+    # prepend even if the variable has not been set yet, in case a shell script sets the
+    # same variable without the knowledge of this Python script.
+    # later _remove_ending_separators() will cleanup any unintentional trailing separator
+    extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name})
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value + extend})
+    if value not in env_state[name]:
+        env_state[name].add(value)
+    else:
+        if not _include_comments():
+            return []
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+# generate commands for removing prepended underscores
+def _remove_ending_separators():
+    # do nothing if the shell extension does not implement the logic
+    if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None:
+        return []
+
+    global env_state
+    commands = []
+    for name in env_state:
+        # skip variables that already had values before this script started prepending
+        if name in os.environ:
+            continue
+        commands += [
+            FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}),
+            FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})]
+    return commands
+
+
+def _set(name, value):
+    global env_state
+    env_state[name] = value
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value})
+    return [line]
+
+
+def _set_if_unset(name, value):
+    global env_state
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value})
+    if env_state.get(name, os.environ.get(name)):
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+if __name__ == '__main__':  # pragma: no cover
+    try:
+        rc = main()
+    except RuntimeError as e:
+        print(str(e), file=sys.stderr)
+        rc = 1
+    sys.exit(rc)
diff --git a/ros2_ws/install/_local_setup_util_sh.py b/ros2_ws/install/_local_setup_util_sh.py
new file mode 100644
index 0000000..35c017b
--- /dev/null
+++ b/ros2_ws/install/_local_setup_util_sh.py
@@ -0,0 +1,404 @@
+# Copyright 2016-2019 Dirk Thomas
+# Licensed under the Apache License, Version 2.0
+
+import argparse
+from collections import OrderedDict
+import os
+from pathlib import Path
+import sys
+
+
+FORMAT_STR_COMMENT_LINE = '# {comment}'
+FORMAT_STR_SET_ENV_VAR = 'export {name}="{value}"'
+FORMAT_STR_USE_ENV_VAR = '${name}'
+FORMAT_STR_INVOKE_SCRIPT = 'COLCON_CURRENT_PREFIX="{prefix}" _colcon_prefix_sh_source_script "{script_path}"'
+FORMAT_STR_REMOVE_LEADING_SEPARATOR = 'if [ "$(echo -n ${name} | head -c 1)" = ":" ]; then export {name}=${{{name}#?}} ; fi'
+FORMAT_STR_REMOVE_TRAILING_SEPARATOR = 'if [ "$(echo -n ${name} | tail -c 1)" = ":" ]; then export {name}=${{{name}%?}} ; fi'
+
+DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate'
+DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate'
+DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists'
+DSV_TYPE_SET = 'set'
+DSV_TYPE_SET_IF_UNSET = 'set-if-unset'
+DSV_TYPE_SOURCE = 'source'
+
+
+def main(argv=sys.argv[1:]):  # noqa: D103
+    parser = argparse.ArgumentParser(
+        description='Output shell commands for the packages in topological '
+                    'order')
+    parser.add_argument(
+        'primary_extension',
+        help='The file extension of the primary shell')
+    parser.add_argument(
+        'additional_extension', nargs='?',
+        help='The additional file extension to be considered')
+    parser.add_argument(
+        '--merged-install', action='store_true',
+        help='All install prefixes are merged into a single location')
+    args = parser.parse_args(argv)
+
+    packages = get_packages(Path(__file__).parent, args.merged_install)
+
+    ordered_packages = order_packages(packages)
+    for pkg_name in ordered_packages:
+        if _include_comments():
+            print(
+                FORMAT_STR_COMMENT_LINE.format_map(
+                    {'comment': 'Package: ' + pkg_name}))
+        prefix = os.path.abspath(os.path.dirname(__file__))
+        if not args.merged_install:
+            prefix = os.path.join(prefix, pkg_name)
+        for line in get_commands(
+            pkg_name, prefix, args.primary_extension,
+            args.additional_extension
+        ):
+            print(line)
+
+    for line in _remove_ending_separators():
+        print(line)
+
+
+def get_packages(prefix_path, merged_install):
+    """
+    Find packages based on colcon-specific files created during installation.
+
+    :param Path prefix_path: The install prefix path of all packages
+    :param bool merged_install: The flag if the packages are all installed
+      directly in the prefix or if each package is installed in a subdirectory
+      named after the package
+    :returns: A mapping from the package name to the set of runtime
+      dependencies
+    :rtype: dict
+    """
+    packages = {}
+    # since importing colcon_core isn't feasible here the following constant
+    # must match colcon_core.location.get_relative_package_index_path()
+    subdirectory = 'share/colcon-core/packages'
+    if merged_install:
+        # return if workspace is empty
+        if not (prefix_path / subdirectory).is_dir():
+            return packages
+        # find all files in the subdirectory
+        for p in (prefix_path / subdirectory).iterdir():
+            if not p.is_file():
+                continue
+            if p.name.startswith('.'):
+                continue
+            add_package_runtime_dependencies(p, packages)
+    else:
+        # for each subdirectory look for the package specific file
+        for p in prefix_path.iterdir():
+            if not p.is_dir():
+                continue
+            if p.name.startswith('.'):
+                continue
+            p = p / subdirectory / p.name
+            if p.is_file():
+                add_package_runtime_dependencies(p, packages)
+
+    # remove unknown dependencies
+    pkg_names = set(packages.keys())
+    for k in packages.keys():
+        packages[k] = {d for d in packages[k] if d in pkg_names}
+
+    return packages
+
+
+def add_package_runtime_dependencies(path, packages):
+    """
+    Check the path and if it exists extract the packages runtime dependencies.
+
+    :param Path path: The resource file containing the runtime dependencies
+    :param dict packages: A mapping from package names to the sets of runtime
+      dependencies to add to
+    """
+    content = path.read_text()
+    dependencies = set(content.split(os.pathsep) if content else [])
+    packages[path.name] = dependencies
+
+
+def order_packages(packages):
+    """
+    Order packages topologically.
+
+    :param dict packages: A mapping from package name to the set of runtime
+      dependencies
+    :returns: The package names
+    :rtype: list
+    """
+    # select packages with no dependencies in alphabetical order
+    to_be_ordered = list(packages.keys())
+    ordered = []
+    while to_be_ordered:
+        pkg_names_without_deps = [
+            name for name in to_be_ordered if not packages[name]]
+        if not pkg_names_without_deps:
+            reduce_cycle_set(packages)
+            raise RuntimeError(
+                'Circular dependency between: ' + ', '.join(sorted(packages)))
+        pkg_names_without_deps.sort()
+        pkg_name = pkg_names_without_deps[0]
+        to_be_ordered.remove(pkg_name)
+        ordered.append(pkg_name)
+        # remove item from dependency lists
+        for k in list(packages.keys()):
+            if pkg_name in packages[k]:
+                packages[k].remove(pkg_name)
+    return ordered
+
+
+def reduce_cycle_set(packages):
+    """
+    Reduce the set of packages to the ones part of the circular dependency.
+
+    :param dict packages: A mapping from package name to the set of runtime
+      dependencies which is modified in place
+    """
+    last_depended = None
+    while len(packages) > 0:
+        # get all remaining dependencies
+        depended = set()
+        for pkg_name, dependencies in packages.items():
+            depended = depended.union(dependencies)
+        # remove all packages which are not dependent on
+        for name in list(packages.keys()):
+            if name not in depended:
+                del packages[name]
+        if last_depended:
+            # if remaining packages haven't changed return them
+            if last_depended == depended:
+                return packages.keys()
+        # otherwise reduce again
+        last_depended = depended
+
+
+def _include_comments():
+    # skipping comment lines when COLCON_TRACE is not set speeds up the
+    # processing especially on Windows
+    return bool(os.environ.get('COLCON_TRACE'))
+
+
+def get_commands(pkg_name, prefix, primary_extension, additional_extension):
+    commands = []
+    package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv')
+    if os.path.exists(package_dsv_path):
+        commands += process_dsv_file(
+            package_dsv_path, prefix, primary_extension, additional_extension)
+    return commands
+
+
+def process_dsv_file(
+    dsv_path, prefix, primary_extension=None, additional_extension=None
+):
+    commands = []
+    if _include_comments():
+        commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path}))
+    with open(dsv_path, 'r') as h:
+        content = h.read()
+    lines = content.splitlines()
+
+    basenames = OrderedDict()
+    for i, line in enumerate(lines):
+        # skip over empty or whitespace-only lines
+        if not line.strip():
+            continue
+        try:
+            type_, remainder = line.split(';', 1)
+        except ValueError:
+            raise RuntimeError(
+                "Line %d in '%s' doesn't contain a semicolon separating the "
+                'type from the arguments' % (i + 1, dsv_path))
+        if type_ != DSV_TYPE_SOURCE:
+            # handle non-source lines
+            try:
+                commands += handle_dsv_types_except_source(
+                    type_, remainder, prefix)
+            except RuntimeError as e:
+                raise RuntimeError(
+                    "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e
+        else:
+            # group remaining source lines by basename
+            path_without_ext, ext = os.path.splitext(remainder)
+            if path_without_ext not in basenames:
+                basenames[path_without_ext] = set()
+            assert ext.startswith('.')
+            ext = ext[1:]
+            if ext in (primary_extension, additional_extension):
+                basenames[path_without_ext].add(ext)
+
+    # add the dsv extension to each basename if the file exists
+    for basename, extensions in basenames.items():
+        if not os.path.isabs(basename):
+            basename = os.path.join(prefix, basename)
+        if os.path.exists(basename + '.dsv'):
+            extensions.add('dsv')
+
+    for basename, extensions in basenames.items():
+        if not os.path.isabs(basename):
+            basename = os.path.join(prefix, basename)
+        if 'dsv' in extensions:
+            # process dsv files recursively
+            commands += process_dsv_file(
+                basename + '.dsv', prefix, primary_extension=primary_extension,
+                additional_extension=additional_extension)
+        elif primary_extension in extensions and len(extensions) == 1:
+            # source primary-only files
+            commands += [
+                FORMAT_STR_INVOKE_SCRIPT.format_map({
+                    'prefix': prefix,
+                    'script_path': basename + '.' + primary_extension})]
+        elif additional_extension in extensions:
+            # source non-primary files
+            commands += [
+                FORMAT_STR_INVOKE_SCRIPT.format_map({
+                    'prefix': prefix,
+                    'script_path': basename + '.' + additional_extension})]
+
+    return commands
+
+
+def handle_dsv_types_except_source(type_, remainder, prefix):
+    commands = []
+    if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET):
+        try:
+            env_name, value = remainder.split(';', 1)
+        except ValueError:
+            raise RuntimeError(
+                "doesn't contain a semicolon separating the environment name "
+                'from the value')
+        try_prefixed_value = os.path.join(prefix, value) if value else prefix
+        if os.path.exists(try_prefixed_value):
+            value = try_prefixed_value
+        if type_ == DSV_TYPE_SET:
+            commands += _set(env_name, value)
+        elif type_ == DSV_TYPE_SET_IF_UNSET:
+            commands += _set_if_unset(env_name, value)
+        else:
+            assert False
+    elif type_ in (
+        DSV_TYPE_APPEND_NON_DUPLICATE,
+        DSV_TYPE_PREPEND_NON_DUPLICATE,
+        DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS
+    ):
+        try:
+            env_name_and_values = remainder.split(';')
+        except ValueError:
+            raise RuntimeError(
+                "doesn't contain a semicolon separating the environment name "
+                'from the values')
+        env_name = env_name_and_values[0]
+        values = env_name_and_values[1:]
+        for value in values:
+            if not value:
+                value = prefix
+            elif not os.path.isabs(value):
+                value = os.path.join(prefix, value)
+            if (
+                type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and
+                not os.path.exists(value)
+            ):
+                comment = f'skip extending {env_name} with not existing ' \
+                    f'path: {value}'
+                if _include_comments():
+                    commands.append(
+                        FORMAT_STR_COMMENT_LINE.format_map({'comment': comment}))
+            elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE:
+                commands += _append_unique_value(env_name, value)
+            else:
+                commands += _prepend_unique_value(env_name, value)
+    else:
+        raise RuntimeError(
+            'contains an unknown environment hook type: ' + type_)
+    return commands
+
+
+env_state = {}
+
+
+def _append_unique_value(name, value):
+    global env_state
+    if name not in env_state:
+        if os.environ.get(name):
+            env_state[name] = set(os.environ[name].split(os.pathsep))
+        else:
+            env_state[name] = set()
+    # append even if the variable has not been set yet, in case a shell script sets the
+    # same variable without the knowledge of this Python script.
+    # later _remove_ending_separators() will cleanup any unintentional leading separator
+    extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': extend + value})
+    if value not in env_state[name]:
+        env_state[name].add(value)
+    else:
+        if not _include_comments():
+            return []
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+def _prepend_unique_value(name, value):
+    global env_state
+    if name not in env_state:
+        if os.environ.get(name):
+            env_state[name] = set(os.environ[name].split(os.pathsep))
+        else:
+            env_state[name] = set()
+    # prepend even if the variable has not been set yet, in case a shell script sets the
+    # same variable without the knowledge of this Python script.
+    # later _remove_ending_separators() will cleanup any unintentional trailing separator
+    extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name})
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value + extend})
+    if value not in env_state[name]:
+        env_state[name].add(value)
+    else:
+        if not _include_comments():
+            return []
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+# generate commands for removing prepended underscores
+def _remove_ending_separators():
+    # do nothing if the shell extension does not implement the logic
+    if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None:
+        return []
+
+    global env_state
+    commands = []
+    for name in env_state:
+        # skip variables that already had values before this script started prepending
+        if name in os.environ:
+            continue
+        commands += [
+            FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}),
+            FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})]
+    return commands
+
+
+def _set(name, value):
+    global env_state
+    env_state[name] = value
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value})
+    return [line]
+
+
+def _set_if_unset(name, value):
+    global env_state
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value})
+    if env_state.get(name, os.environ.get(name)):
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+if __name__ == '__main__':  # pragma: no cover
+    try:
+        rc = main()
+    except RuntimeError as e:
+        print(str(e), file=sys.stderr)
+        rc = 1
+    sys.exit(rc)
diff --git a/ros2_ws/install/local_setup.bash b/ros2_ws/install/local_setup.bash
new file mode 100644
index 0000000..efd5f8c
--- /dev/null
+++ b/ros2_ws/install/local_setup.bash
@@ -0,0 +1,107 @@
+# generated from colcon_bash/shell/template/prefix.bash.em
+
+# This script extends the environment with all packages contained in this
+# prefix path.
+
+# a bash script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)"
+else
+  _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prefix_bash_prepend_unique_value() {
+  # arguments
+  _listname="$1"
+  _value="$2"
+
+  # get values from variable
+  eval _values=\"\$$_listname\"
+  # backup the field separator
+  _colcon_prefix_bash_prepend_unique_value_IFS="$IFS"
+  IFS=":"
+  # start with the new value
+  _all_values="$_value"
+  # iterate over existing values in the variable
+  for _item in $_values; do
+    # ignore empty strings
+    if [ -z "$_item" ]; then
+      continue
+    fi
+    # ignore duplicates of _value
+    if [ "$_item" = "$_value" ]; then
+      continue
+    fi
+    # keep non-duplicate values
+    _all_values="$_all_values:$_item"
+  done
+  unset _item
+  # restore the field separator
+  IFS="$_colcon_prefix_bash_prepend_unique_value_IFS"
+  unset _colcon_prefix_bash_prepend_unique_value_IFS
+  # export the updated variable
+  eval export $_listname=\"$_all_values\"
+  unset _all_values
+  unset _values
+
+  unset _value
+  unset _listname
+}
+
+# add this prefix to the COLCON_PREFIX_PATH
+_colcon_prefix_bash_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX"
+unset _colcon_prefix_bash_prepend_unique_value
+
+# check environment variable for custom Python executable
+if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then
+  if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then
+    echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist"
+    return 1
+  fi
+  _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE"
+else
+  # try the Python executable known at configure time
+  _colcon_python_executable="/usr/bin/python3"
+  # if it doesn't exist try a fall back
+  if [ ! -f "$_colcon_python_executable" ]; then
+    if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then
+      echo "error: unable to find python3 executable"
+      return 1
+    fi
+    _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"`
+  fi
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_sh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo ". \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# get all commands in topological order
+_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh bash)"
+unset _colcon_python_executable
+if [ -n "$COLCON_TRACE" ]; then
+  echo "Execute generated script:"
+  echo "<<<"
+  echo "${_colcon_ordered_commands}"
+  echo ">>>"
+fi
+eval "${_colcon_ordered_commands}"
+unset _colcon_ordered_commands
+
+unset _colcon_prefix_sh_source_script
+
+unset _colcon_prefix_bash_COLCON_CURRENT_PREFIX
diff --git a/ros2_ws/install/local_setup.ps1 b/ros2_ws/install/local_setup.ps1
new file mode 100644
index 0000000..6f68c8d
--- /dev/null
+++ b/ros2_ws/install/local_setup.ps1
@@ -0,0 +1,55 @@
+# generated from colcon_powershell/shell/template/prefix.ps1.em
+
+# This script extends the environment with all packages contained in this
+# prefix path.
+
+# check environment variable for custom Python executable
+if ($env:COLCON_PYTHON_EXECUTABLE) {
+  if (!(Test-Path "$env:COLCON_PYTHON_EXECUTABLE" -PathType Leaf)) {
+    echo "error: COLCON_PYTHON_EXECUTABLE '$env:COLCON_PYTHON_EXECUTABLE' doesn't exist"
+    exit 1
+  }
+  $_colcon_python_executable="$env:COLCON_PYTHON_EXECUTABLE"
+} else {
+  # use the Python executable known at configure time
+  $_colcon_python_executable="/usr/bin/python3"
+  # if it doesn't exist try a fall back
+  if (!(Test-Path "$_colcon_python_executable" -PathType Leaf)) {
+    if (!(Get-Command "python3" -ErrorAction SilentlyContinue)) {
+      echo "error: unable to find python3 executable"
+      exit 1
+    }
+    $_colcon_python_executable="python3"
+  }
+}
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+function _colcon_prefix_powershell_source_script {
+  param (
+    $_colcon_prefix_powershell_source_script_param
+  )
+  # source script with conditional trace output
+  if (Test-Path $_colcon_prefix_powershell_source_script_param) {
+    if ($env:COLCON_TRACE) {
+      echo ". '$_colcon_prefix_powershell_source_script_param'"
+    }
+    . "$_colcon_prefix_powershell_source_script_param"
+  } else {
+    Write-Error "not found: '$_colcon_prefix_powershell_source_script_param'"
+  }
+}
+
+# get all commands in topological order
+$_colcon_ordered_commands = & "$_colcon_python_executable" "$(Split-Path $PSCommandPath -Parent)/_local_setup_util_ps1.py" ps1
+
+# execute all commands in topological order
+if ($env:COLCON_TRACE) {
+  echo "Execute generated script:"
+  echo "<<<"
+  $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Write-Output
+  echo ">>>"
+}
+if ($_colcon_ordered_commands) {
+  $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Invoke-Expression
+}
diff --git a/ros2_ws/install/local_setup.sh b/ros2_ws/install/local_setup.sh
new file mode 100644
index 0000000..ef8aee8
--- /dev/null
+++ b/ros2_ws/install/local_setup.sh
@@ -0,0 +1,137 @@
+# generated from colcon_core/shell/template/prefix.sh.em
+
+# This script extends the environment with all packages contained in this
+# prefix path.
+
+# since a plain shell script can't determine its own path when being sourced
+# either use the provided COLCON_CURRENT_PREFIX
+# or fall back to the build time prefix (if it exists)
+_colcon_prefix_sh_COLCON_CURRENT_PREFIX="/home/ubuntu/ros2_ws/install"
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  if [ ! -d "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX" ]; then
+    echo "The build time path \"$_colcon_prefix_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2
+    unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX
+    return 1
+  fi
+else
+  _colcon_prefix_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prefix_sh_prepend_unique_value() {
+  # arguments
+  _listname="$1"
+  _value="$2"
+
+  # get values from variable
+  eval _values=\"\$$_listname\"
+  # backup the field separator
+  _colcon_prefix_sh_prepend_unique_value_IFS="$IFS"
+  IFS=":"
+  # start with the new value
+  _all_values="$_value"
+  _contained_value=""
+  # iterate over existing values in the variable
+  for _item in $_values; do
+    # ignore empty strings
+    if [ -z "$_item" ]; then
+      continue
+    fi
+    # ignore duplicates of _value
+    if [ "$_item" = "$_value" ]; then
+      _contained_value=1
+      continue
+    fi
+    # keep non-duplicate values
+    _all_values="$_all_values:$_item"
+  done
+  unset _item
+  if [ -z "$_contained_value" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      if [ "$_all_values" = "$_value" ]; then
+        echo "export $_listname=$_value"
+      else
+        echo "export $_listname=$_value:\$$_listname"
+      fi
+    fi
+  fi
+  unset _contained_value
+  # restore the field separator
+  IFS="$_colcon_prefix_sh_prepend_unique_value_IFS"
+  unset _colcon_prefix_sh_prepend_unique_value_IFS
+  # export the updated variable
+  eval export $_listname=\"$_all_values\"
+  unset _all_values
+  unset _values
+
+  unset _value
+  unset _listname
+}
+
+# add this prefix to the COLCON_PREFIX_PATH
+_colcon_prefix_sh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX"
+unset _colcon_prefix_sh_prepend_unique_value
+
+# check environment variable for custom Python executable
+if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then
+  if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then
+    echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist"
+    return 1
+  fi
+  _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE"
+else
+  # try the Python executable known at configure time
+  _colcon_python_executable="/usr/bin/python3"
+  # if it doesn't exist try a fall back
+  if [ ! -f "$_colcon_python_executable" ]; then
+    if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then
+      echo "error: unable to find python3 executable"
+      return 1
+    fi
+    _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"`
+  fi
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_sh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# get all commands in topological order
+_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh)"
+unset _colcon_python_executable
+if [ -n "$COLCON_TRACE" ]; then
+  echo "_colcon_prefix_sh_source_script() {
+    if [ -f \"\$1\" ]; then
+      if [ -n \"\$COLCON_TRACE\" ]; then
+        echo \"# . \\\"\$1\\\"\"
+      fi
+      . \"\$1\"
+    else
+      echo \"not found: \\\"\$1\\\"\" 1>&2
+    fi
+  }"
+  echo "# Execute generated script:"
+  echo "# <<<"
+  echo "${_colcon_ordered_commands}"
+  echo "# >>>"
+  echo "unset _colcon_prefix_sh_source_script"
+fi
+eval "${_colcon_ordered_commands}"
+unset _colcon_ordered_commands
+
+unset _colcon_prefix_sh_source_script
+
+unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX
diff --git a/ros2_ws/install/local_setup.zsh b/ros2_ws/install/local_setup.zsh
new file mode 100644
index 0000000..f7a8d90
--- /dev/null
+++ b/ros2_ws/install/local_setup.zsh
@@ -0,0 +1,120 @@
+# generated from colcon_zsh/shell/template/prefix.zsh.em
+
+# This script extends the environment with all packages contained in this
+# prefix path.
+
+# a zsh script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)"
+else
+  _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to convert array-like strings into arrays
+# to workaround SH_WORD_SPLIT not being set
+_colcon_prefix_zsh_convert_to_array() {
+  local _listname=$1
+  local _dollar="$"
+  local _split="{="
+  local _to_array="(\"$_dollar$_split$_listname}\")"
+  eval $_listname=$_to_array
+}
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prefix_zsh_prepend_unique_value() {
+  # arguments
+  _listname="$1"
+  _value="$2"
+
+  # get values from variable
+  eval _values=\"\$$_listname\"
+  # backup the field separator
+  _colcon_prefix_zsh_prepend_unique_value_IFS="$IFS"
+  IFS=":"
+  # start with the new value
+  _all_values="$_value"
+  # workaround SH_WORD_SPLIT not being set
+  _colcon_prefix_zsh_convert_to_array _values
+  # iterate over existing values in the variable
+  for _item in $_values; do
+    # ignore empty strings
+    if [ -z "$_item" ]; then
+      continue
+    fi
+    # ignore duplicates of _value
+    if [ "$_item" = "$_value" ]; then
+      continue
+    fi
+    # keep non-duplicate values
+    _all_values="$_all_values:$_item"
+  done
+  unset _item
+  # restore the field separator
+  IFS="$_colcon_prefix_zsh_prepend_unique_value_IFS"
+  unset _colcon_prefix_zsh_prepend_unique_value_IFS
+  # export the updated variable
+  eval export $_listname=\"$_all_values\"
+  unset _all_values
+  unset _values
+
+  unset _value
+  unset _listname
+}
+
+# add this prefix to the COLCON_PREFIX_PATH
+_colcon_prefix_zsh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX"
+unset _colcon_prefix_zsh_prepend_unique_value
+unset _colcon_prefix_zsh_convert_to_array
+
+# check environment variable for custom Python executable
+if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then
+  if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then
+    echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist"
+    return 1
+  fi
+  _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE"
+else
+  # try the Python executable known at configure time
+  _colcon_python_executable="/usr/bin/python3"
+  # if it doesn't exist try a fall back
+  if [ ! -f "$_colcon_python_executable" ]; then
+    if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then
+      echo "error: unable to find python3 executable"
+      return 1
+    fi
+    _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"`
+  fi
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_sh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo ". \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# get all commands in topological order
+_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh zsh)"
+unset _colcon_python_executable
+if [ -n "$COLCON_TRACE" ]; then
+  echo "Execute generated script:"
+  echo "<<<"
+  echo "${_colcon_ordered_commands}"
+  echo ">>>"
+fi
+eval "${_colcon_ordered_commands}"
+unset _colcon_ordered_commands
+
+unset _colcon_prefix_sh_source_script
+
+unset _colcon_prefix_zsh_COLCON_CURRENT_PREFIX
diff --git a/ros2_ws/install/setup.bash b/ros2_ws/install/setup.bash
new file mode 100644
index 0000000..4c55244
--- /dev/null
+++ b/ros2_ws/install/setup.bash
@@ -0,0 +1,31 @@
+# generated from colcon_bash/shell/template/prefix_chain.bash.em
+
+# This script extends the environment with the environment of other prefix
+# paths which were sourced when this file was generated as well as all packages
+# contained in this prefix path.
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_chain_bash_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo ". \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# source chained prefixes
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script
+COLCON_CURRENT_PREFIX="/opt/ros/humble"
+_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash"
+
+# source this prefix
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script
+COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)"
+_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash"
+
+unset COLCON_CURRENT_PREFIX
+unset _colcon_prefix_chain_bash_source_script
diff --git a/ros2_ws/install/setup.ps1 b/ros2_ws/install/setup.ps1
new file mode 100644
index 0000000..558e9b9
--- /dev/null
+++ b/ros2_ws/install/setup.ps1
@@ -0,0 +1,29 @@
+# generated from colcon_powershell/shell/template/prefix_chain.ps1.em
+
+# This script extends the environment with the environment of other prefix
+# paths which were sourced when this file was generated as well as all packages
+# contained in this prefix path.
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+function _colcon_prefix_chain_powershell_source_script {
+  param (
+    $_colcon_prefix_chain_powershell_source_script_param
+  )
+  # source script with conditional trace output
+  if (Test-Path $_colcon_prefix_chain_powershell_source_script_param) {
+    if ($env:COLCON_TRACE) {
+      echo ". '$_colcon_prefix_chain_powershell_source_script_param'"
+    }
+    . "$_colcon_prefix_chain_powershell_source_script_param"
+  } else {
+    Write-Error "not found: '$_colcon_prefix_chain_powershell_source_script_param'"
+  }
+}
+
+# source chained prefixes
+_colcon_prefix_chain_powershell_source_script "/opt/ros/humble\local_setup.ps1"
+
+# source this prefix
+$env:COLCON_CURRENT_PREFIX=(Split-Path $PSCommandPath -Parent)
+_colcon_prefix_chain_powershell_source_script "$env:COLCON_CURRENT_PREFIX\local_setup.ps1"
diff --git a/ros2_ws/install/setup.sh b/ros2_ws/install/setup.sh
new file mode 100644
index 0000000..5b2b7fe
--- /dev/null
+++ b/ros2_ws/install/setup.sh
@@ -0,0 +1,45 @@
+# generated from colcon_core/shell/template/prefix_chain.sh.em
+
+# This script extends the environment with the environment of other prefix
+# paths which were sourced when this file was generated as well as all packages
+# contained in this prefix path.
+
+# since a plain shell script can't determine its own path when being sourced
+# either use the provided COLCON_CURRENT_PREFIX
+# or fall back to the build time prefix (if it exists)
+_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX=/home/ubuntu/ros2_ws/install
+if [ ! -z "$COLCON_CURRENT_PREFIX" ]; then
+  _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+elif [ ! -d "$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX" ]; then
+  echo "The build time path \"$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2
+  unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX
+  return 1
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_chain_sh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# source chained prefixes
+# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script
+COLCON_CURRENT_PREFIX="/opt/ros/humble"
+_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh"
+
+
+# source this prefix
+# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script
+COLCON_CURRENT_PREFIX="$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX"
+_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh"
+
+unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX
+unset _colcon_prefix_chain_sh_source_script
+unset COLCON_CURRENT_PREFIX
diff --git a/ros2_ws/install/setup.zsh b/ros2_ws/install/setup.zsh
new file mode 100644
index 0000000..990d171
--- /dev/null
+++ b/ros2_ws/install/setup.zsh
@@ -0,0 +1,31 @@
+# generated from colcon_zsh/shell/template/prefix_chain.zsh.em
+
+# This script extends the environment with the environment of other prefix
+# paths which were sourced when this file was generated as well as all packages
+# contained in this prefix path.
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_chain_zsh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo ". \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# source chained prefixes
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script
+COLCON_CURRENT_PREFIX="/opt/ros/humble"
+_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh"
+
+# source this prefix
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script
+COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)"
+_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh"
+
+unset COLCON_CURRENT_PREFIX
+unset _colcon_prefix_chain_zsh_source_script
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/PKG-INFO b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/PKG-INFO
new file mode 100644
index 0000000..1772b2b
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/PKG-INFO
@@ -0,0 +1,12 @@
+Metadata-Version: 2.1
+Name: sphero-mini-controller
+Version: 0.0.0
+Summary: TODO: Package description
+Home-page: UNKNOWN
+Maintainer: ubuntu
+Maintainer-email: ubuntu@todo.todo
+License: TODO: License declaration
+Platform: UNKNOWN
+
+UNKNOWN
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/SOURCES.txt b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/SOURCES.txt
new file mode 100644
index 0000000..450bb51
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/SOURCES.txt
@@ -0,0 +1,20 @@
+package.xml
+setup.cfg
+setup.py
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt
+../../build/sphero_mini_controller/sphero_mini_controller.egg-info/zip-safe
+resource/sphero_mini_controller
+sphero_mini_controller/WavefrontPlanner.py
+sphero_mini_controller/__init__.py
+sphero_mini_controller/_constants.py
+sphero_mini_controller/blobErkennung.py
+sphero_mini_controller/my_first_node.py
+sphero_mini_controller/treiber.py
+test/test_copyright.py
+test/test_flake8.py
+test/test_pep257.py
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/dependency_links.txt b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/entry_points.txt b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/entry_points.txt
new file mode 100644
index 0000000..6a40ae6
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/entry_points.txt
@@ -0,0 +1,3 @@
+[console_scripts]
+sphero_mini = sphero_mini_controller.my_first_node:main
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/requires.txt b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/requires.txt
new file mode 100644
index 0000000..49fe098
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/requires.txt
@@ -0,0 +1 @@
+setuptools
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/top_level.txt b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/top_level.txt
new file mode 100644
index 0000000..60845da
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/top_level.txt
@@ -0,0 +1 @@
+sphero_mini_controller
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/zip-safe b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info/zip-safe
@@ -0,0 +1 @@
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/GameWavefront.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/GameWavefront.py
new file mode 100644
index 0000000..aae934f
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/GameWavefront.py
@@ -0,0 +1,375 @@
+# Wavefront Planning
+# Sajad Saeedi, Andrew Davison 2017
+# Implementation is based on the following reference
+#
+# H. Choset, K. M. Lynch, S. Hutchinson, G. Kantor, W. Burgard, L. E. Kavraki and S. Thrun,
+# Principles of Robot Motion: Theory, Algorithms, and Implementations,
+# MIT Press, Boston, 2005.
+# http://www.cs.cmu.edu/afs/cs/Web/People/motionplanning/ 
+#
+# From Chapter 4.5 - Wave-Front Planner
+# This planner determines a path via gradient descent on the grid starting from the start. 
+# Essentially, the planner determines the path one pixel at a time.
+# The wave-front planner essentially forms a potential function on the grid which has one local minimum and thus is resolution complete. 
+# The planner also determines the shortest path, but at the cost of coming dangerously close to obstacles. 
+# The major drawback of this method is that the planner has to search the entire space for a path
+
+import pygame, os, math, time, random
+import numpy as np
+try:
+    import pygame
+    from pygame import surfarray
+    from pygame.locals import *
+except ImportError:
+    raise ImportError('Error Importing Pygame/surfarray')
+    
+pygame.init()
+
+SCALE = 1
+
+# set the width and height of the screen
+WIDTH = 1500/SCALE
+HEIGHT = 1000/SCALE
+
+# The region we will fill with obstacles
+PLAYFIELDCORNERS = (-3.0, -3.0, 3.0, 3.0)
+
+# Barrier locations
+barriers = []
+# barrier contents are (bx, by, visibilitymask)
+for i in range(100):
+	(bx, by) = (random.uniform(PLAYFIELDCORNERS[0], PLAYFIELDCORNERS[2]), random.uniform(PLAYFIELDCORNERS[1], PLAYFIELDCORNERS[3]))
+	barrier = [bx, by, 0]
+	barriers.append(barrier)
+
+BARRIERRADIUS = 0.1
+
+
+ROBOTRADIUS = 0.15
+W = 2 * ROBOTRADIUS
+SAFEDIST = 0.2
+BARRIERINFILATE = ROBOTRADIUS
+
+MAXVELOCITY = 0.5     #ms^(-1) max speed of each wheel
+MAXACCELERATION = 0.5 #ms^(-2) max rate we can change speed of each wheel
+
+target = (PLAYFIELDCORNERS[2] + 1.0, 0)
+
+k = 160/SCALE # pixels per metre for graphics
+u0 = WIDTH / 2
+v0 = HEIGHT / 2
+
+x = PLAYFIELDCORNERS[0] - 0.5
+y = 0.0
+theta = 0.0
+
+vL = 0.00
+vR = 0.00
+
+size = [int(WIDTH), int(HEIGHT)]
+screen = pygame.display.set_mode(size)
+black = (20,20,40)
+
+# This makes the normal mouse pointer invisible in graphics window
+pygame.mouse.set_visible(0)
+
+# time delta
+dt = 0.1
+
+
+def surfdemo_show(array_img, name):
+	"displays a surface, waits for user to continue"
+	screen = pygame.display.set_mode(array_img.shape[:2], 0, 32)
+	surfarray.blit_array(screen, array_img)
+	pygame.display.flip()
+	pygame.display.set_caption(name)
+	while 1:
+		e = pygame.event.wait()
+		if e.type == MOUSEBUTTONDOWN: break
+		if e.type == KEYDOWN: break
+
+
+def predictPosition(vL, vR, x, y, theta, dt):
+
+	# Position update in time dt
+
+	# Special cases
+	# Straight line motion
+	if (vL == vR): 
+		xnew = x + vL * dt * math.cos(theta)
+		ynew = y + vL * dt * math.sin(theta)
+		thetanew = theta
+	# Pure rotation motion
+	elif (vL == -vR):
+		xnew = x
+		ynew = y
+		thetanew = theta + ((vR - vL) * dt / W)
+	else:
+		# Rotation and arc angle of general circular motion
+		R = W / 2.0 * (vR + vL) / (vR - vL)
+		deltatheta = (vR - vL) * dt / W
+		xnew = x + R * (math.sin(deltatheta + theta) - math.sin(theta))
+		ynew = y - R * (math.cos(deltatheta + theta) - math.cos(theta))
+		thetanew = theta + deltatheta
+	
+	return (xnew, ynew, thetanew)
+
+
+def drawBarriers(barriers):
+	for barrier in barriers:
+		if(barrier[2] == 0):
+			pygame.draw.circle(screen, (0,20,80), (int(u0 + k * barrier[0]), int(v0 - k * barrier[1])), int(k * BARRIERRADIUS), 0)
+		else:
+			pygame.draw.circle(screen, (0,120,255), (int(u0 + k * barrier[0]), int(v0 - k * barrier[1])), int(k * BARRIERRADIUS), 0)
+	return
+	
+def dialtebarrieres(imgin, barriers):
+	imgout = imgin
+	for barrier in barriers:
+		if(barrier[2] == 0):
+			center_u = int(u0 + k * barrier[0])
+			center_v = int(v0 - k * barrier[1])
+			RAD = BARRIERRADIUS+BARRIERINFILATE
+			radius = int(k * (RAD))
+			radius2 = int(k * (BARRIERRADIUS))
+			points = [(x,y) for x in range(center_u-radius, center_u+radius) for y in range(center_v-radius, center_v+radius)]
+			for pt in points:
+				vu = center_u - pt[0]
+				vv = center_v - pt[1]
+				distance = math.sqrt(vv*vv + vu*vu)
+				if (distance < radius and distance > radius2 and pt[0] < WIDTH-1 and pt[1] < HEIGHT-1):
+					imgout[pt[0],pt[1],0] = 0
+					imgout[pt[0],pt[1],1] = 40
+					imgout[pt[0],pt[1],2] = 80
+	return imgout
+	
+def MakeWaveFront(imgarray, start_uv, target_uv):
+	print ("building wavefront, please wait ... ")	
+	heap = []
+	newheap = []
+
+	u = target_uv[0]
+	v = target_uv[1]
+
+	imgarray[:,:,0] = 0 # use channel 0 for planning
+	imgarray[u, v, 0] = 2
+
+	lastwave = 3 	# start by setting nodes around target to 3
+	moves = [(u + 1, v), (u - 1, v), (u, v - 1), (u, v + 1)]
+	for move in moves:
+		imgarray[move[0], move[1], 0] = 3
+		heap.append(move)
+
+	path = False
+	max_search = int(np.sqrt(WIDTH*WIDTH + HEIGHT*HEIGHT))
+	for currentwave in range(4, max_search):
+		lastwave = lastwave + 1
+		while(heap != []):
+			position = heap.pop()
+			(u, v) = position
+			moves = [(u + 1, v), (u - 1, v), (u, v + 1), (u, v - 1)]
+			for move in moves:
+				if(imgarray[move[0], move[1], 2] != 80):
+					if(imgarray[move[0], move[1], 0] == 0 and imgarray[position[0], position[1], 0] == currentwave - 1 and move[0] < WIDTH-1 and move[1] < HEIGHT-1 and move[0]>2 and move[1]>2):
+						imgarray[move[0], move[1], 0] = currentwave
+						newheap.append(move)
+					if(move == start_uv):
+						path = True
+						break 	
+			if(path == True):
+				break			
+		if(path == True):
+			break
+		heap = newheap
+		newheap = []
+	return imgarray, currentwave
+
+
+def FindPath(imgarray, start_uv, currentwave):
+	trajectory = []	
+	nextpt = start_uv
+	path = []
+	for backwave in range(currentwave-1,2,-1):
+		path.append(nextpt)
+		(u,v) = nextpt
+		values = []
+		val = []
+		moves = [(u + 1, v), (u - 1, v), (u, v + 1), (u, v - 1), (u + 1, v + 1), (u - 1, v - 1), (u + 1, v - 1), (u - 1, v - 1)]
+		for move in moves:
+			val.append(imgarray[move[0], move[1], 0])
+			if(imgarray[move[0], move[1], 0] == backwave):
+				values.append(imgarray[move[0], move[1], 0])
+		minimum = min(values)
+		indices = [i for i, v in enumerate(val) if v == minimum]
+		nextid = random.choice(indices)
+		nextpt = moves[nextid]	
+	return path
+
+def GetControl(x,y,theta, waypoint):
+	wpu = waypoint[0]
+	wpv = waypoint[1]
+	
+	vt = 0.2
+	u = u0 + k * x
+	v = v0 - k * y
+	vector = (wpu - u, -wpv + v)
+	vectorangle = math.atan2(vector[1], vector[0])
+	psi = vectorangle - theta
+
+	if(abs(psi) > (2*3.14/180)):
+		if(psi > 0):
+			vR = vt/2
+			vL = -vt/2
+		else:
+			vR = -vt/2
+			vL = vt/2
+	else:
+		wlx = x - (W/2.0) * math.sin(theta)
+		wly = y + (W/2.0) * math.cos(theta)	
+		ulx = u0 + k * wlx
+		vlx = v0 - k * wly
+		dl = math.sqrt((ulx-wpu)*(ulx-wpu) + (vlx-wpv)*(vlx-wpv))  
+		
+		wrx = x + (W/2.0) * math.sin(theta)
+		wry = y - (W/2.0) * math.cos(theta)
+		urx = u0 + k * wrx
+		vrx = v0 - k * wry
+		dr = math.sqrt((urx-wpu)*(urx-wpu) + (vrx-wpv)*(vrx-wpv))
+		
+		vR = 1*(2*vt)/(1+(dl/dr))
+		vL = 1*(2*vt - vR)
+
+	return vL, vR
+
+def AnimateRobot(x,y,theta):
+	# Draw robot
+	u = u0 + k * x
+	v = v0 - k * y
+	pygame.draw.circle(screen, (255,255,255), (int(u), int(v)), int(k * ROBOTRADIUS), 3)
+	# Draw wheels
+	# left wheel centre 
+	wlx = x - (W/2.0) * math.sin(theta)
+	wly = y + (W/2.0) * math.cos(theta)
+	ulx = u0 + k * wlx
+	vlx = v0 - k * wly
+	WHEELBLOB = 0.04
+	pygame.draw.circle(screen, (0,0,255), (int(ulx), int(vlx)), int(k * WHEELBLOB))
+	# right wheel centre 
+	wrx = x + (W/2.0) * math.sin(theta)
+	wry = y - (W/2.0) * math.cos(theta)
+	urx = u0 + k * wrx
+	vrx = v0 - k * wry
+	pygame.draw.circle(screen, (0,0,255), (int(urx), int(vrx)), int(k * WHEELBLOB))
+
+	time.sleep(dt / 5)
+	pygame.display.flip()
+	#time.sleep(0.2)
+
+def AnimateNavigation(barriers, waypint, path):
+	screen.fill(black)
+	drawBarriers(barriers)
+	
+	for pt in path:
+		screen.set_at(pt, (255,255,255))
+	
+	pygame.draw.circle(screen, (255,100,0), target_uv, int(k * ROBOTRADIUS), 0)		
+	pygame.draw.circle(screen, (255,100,0), (int(u0 + k * target[0]), int(v0 - k * target[1])), int(k * ROBOTRADIUS), 0)
+	pygame.draw.circle(screen, (255,0,255), (int(waypint[0]), int(waypint[1])), int(5))
+		
+def AnimatePath(imgarray, path, start_uv):
+	for pt in path:
+		imgarray[pt[0], pt[1], 0] = 0
+		imgarray[pt[0], pt[1], 1] = 255
+		imgarray[pt[0], pt[1], 2] = 255
+				
+	#imgarray[:,:,0] /= imgarray[:,:,0].max()/255.0
+	scalefactor = imgarray[:,:,0].max()/255.0
+	imgarray[:,:,0] = imgarray[:,:,0]/scalefactor
+	imgarray[:,:,0].astype(int)
+	imgarray[start_uv[0], start_uv[1], 0] = 0
+	imgarray[start_uv[0], start_uv[1], 1] = 255
+	imgarray[start_uv[0], start_uv[1], 2] = 255
+
+	surfdemo_show(imgarray, 'Wavefront Path Planning')	
+
+
+def GetWaypoint(x,y,theta, path, waypointIndex, waypointSeperation, target):
+	reset = False
+	waypoint = path[waypointIndex]
+	u = u0 + k * x
+	v = v0 - k * y
+	distance_to_wp = math.sqrt((waypoint[0]-u)**2+(waypoint[1]-v)**2) # todo compare distance in metrics
+	if(distance_to_wp < 3):
+		waypointIndex = waypointSeperation + waypointIndex 
+		if(waypointIndex > len(path)):
+			waypointIndex = len(path) - 1
+
+	return waypoint, reset, waypointIndex
+
+def IsAtTarget(x,y,target):
+	disttotarget = math.sqrt((x - target[0])**2 + (y - target[1])**2)
+	if (disttotarget < 0.04):
+		return True
+	else:
+		return False
+
+
+while(1):
+	start_uv  = (int(u0 + k * x), int(v0 - k * y)) 
+	target_uv = (int(u0 + k * target[0]), int(v0 - k * target[1]))
+	print ("start is: ", start_uv)
+	print ("goal  is: ", target_uv)
+
+	# prepare map of the world for plannign
+	screen.fill(black)
+	drawBarriers(barriers)
+	pygame.draw.circle(screen, (255,100,0), target_uv, int(k * ROBOTRADIUS), 0)
+	pygame.draw.circle(screen, (255,255,0), start_uv,  int(k * ROBOTRADIUS), 0)
+	imgscreen8  = pygame.surfarray.array3d(screen)
+	imgscreen16 = np.array(imgscreen8, dtype=np.uint16)
+	drawBarriers(barriers)
+	imgarray = dialtebarrieres(imgscreen16, barriers)
+	pygame.display.flip()
+	pygame.display.set_caption('Wavefront Path Planning')
+	
+	# build wavefront, given the map, start point, and target point
+	imgarray, currentwave = MakeWaveFront(imgarray, start_uv, target_uv)
+	print ("press a key to start navaigation ... ")
+
+	# find the path using the wavefront	
+	path = FindPath(imgarray, start_uv, currentwave)
+	
+	# normlaize and show the path on the map
+	AnimatePath(imgarray, path, start_uv)
+
+	# set start point
+	x = PLAYFIELDCORNERS[0] - 0.5
+	y = 0
+	theta = 0
+	waypointSeperation = 40;
+	waypointIndex = waypointSeperation;
+
+	# loop to navigate the path from start to target	
+	while(1):		
+		# get a waypoint to follow the path
+		(waypoint, reset, waypointIndex)= GetWaypoint(x,y,theta, path, waypointIndex, waypointSeperation, target)
+
+		# reset the simulation, if robot is at target
+		if (IsAtTarget(x,y,target)): 
+			target = (target[0], random.uniform(PLAYFIELDCORNERS[1], PLAYFIELDCORNERS[3]))
+			x = PLAYFIELDCORNERS[0] - 0.5
+			y = 0.0
+			theta = 0.0
+			break
+
+
+		# calculate control signals to get to the next waypoint
+		(vL, vR) = GetControl(x,y,theta, waypoint)
+
+		# Actually now move and update position based on chosen vL and vR
+		(x, y, theta) = predictPosition(vL, vR, x, y, theta, dt)
+
+		# animate 	
+		AnimateNavigation(barriers, waypoint, path)
+		AnimateRobot(x,y,theta)	
+		
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontChatGpt.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontChatGpt.py
new file mode 100644
index 0000000..a358dfa
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontChatGpt.py
@@ -0,0 +1,53 @@
+import numpy as np
+import cv2
+import matplotlib.pyplot as plt
+import time
+
+class WaveFrontPlanner:
+    __wall = 999
+    __goal = 1
+    __nothing = '000'
+    __path = 'PATH'
+
+    def __init__(self, mask_list):
+        if not isinstance(mask_list, np.ndarray):
+            raise ValueError("Invalid input type. 'mask_list' must be a numpy array.")
+        self.__mapOfWorld = np.array([['999' if j > 200 else '000' for j in row] for row in mask_list])
+
+    def minSurroundingNodeValue(self, x, y):
+        values = [self.__mapOfWorld[x + 1][y], self.__mapOfWorld[x - 1][y],
+                  self.__mapOfWorld[x][y + 1], self.__mapOfWorld[x][y - 1]]
+        min_value = min(value for value in values if value != self.__nothing)
+        min_index = values.index(min_value) + 1
+        return min_value, min_index
+
+    def waveFrontAlgorithm(self):
+        goal_coordinates = np.where(self.__mapOfWorld == self.__goal)
+        goal_x, goal_y = goal_coordinates[0][0], goal_coordinates[1][0]
+        queue = [(goal_x, goal_y)]
+
+        while queue:
+            x, y = queue.pop(0)
+
+            if self.__mapOfWorld[x][y] == self.__nothing:
+                min_value, min_index = self.minSurroundingNodeValue(x, y)
+                self.__mapOfWorld[x][y] = min_value + 1
+                queue.append((x + 1, y))  # Move down
+                queue.append((x - 1, y))  # Move up
+                queue.append((x, y + 1))  # Move right
+                queue.append((x, y - 1))  # Move left
+
+        self.__mapOfWorld[goal_x][goal_y] = self.__goal
+
+    def visualizeMap(self):
+        plt.imshow(cv2.flip(self.__mapOfWorld, 0), cmap='hot', interpolation='nearest')
+        plt.colorbar()
+        plt.show()
+
+# Beispielverwendung:
+mask_list = np.zeros((200, 200))
+mask_list[50:150, 50:150] = 1
+
+planner = WaveFrontPlanner(mask_list)
+planner.waveFrontAlgorithm()
+planner.visualizeMap()
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontPlanner.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontPlanner.py
new file mode 100644
index 0000000..13cebc9
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/WavefrontPlanner.py
@@ -0,0 +1,397 @@
+############################################################################
+# WAVEFRONT ALGORITHM
+# Adapted to Python Code By Darin Velarde
+# Fri Jan 29 13:56:53 PST 2010
+# from C code from John Palmisano 
+# (www.societyofrobots.com)
+############################################################################
+import cv2
+import numpy as np
+import matplotlib.pyplot as plt
+import time
+
+class waveFrontPlanner:
+    ############################################################################
+    # WAVEFRONT ALGORITHM
+    # Adapted to Python Code By Darin Velarde
+    # Fri Jan 29 13:56:53 PST 2010
+    # from C code from John Palmisano 
+    # (www.societyofrobots.com)
+    ############################################################################
+
+    def __init__(self, mapOfWorld, slow=False):
+        self.__slow = slow
+        self.__mapOfWorld = mapOfWorld
+        if str(type(mapOfWorld)).find("numpy") != -1:
+            #If its a numpy array
+            self.__height, self.__width = self.__mapOfWorld.shape
+        else:
+            self.__height, self.__width = len(self.__mapOfWorld), len(self.__mapOfWorld[0])
+
+        self.__nothing = 000
+        self.__wall = 999
+        self.__goal = 1
+        self.__path = "PATH"
+
+        self.__finalPath = []
+
+        #Robot value
+        self.__robot = 254
+        #Robot default Location
+        self.__robot_x = 0
+        self.__robot_y = 0
+
+        #default goal location
+        self.__goal_x = 8
+        self.__goal_y = 9
+
+        #temp variables
+        self.__temp_A = 0
+        self.__temp_B = 0
+        self.__counter = 0
+        self.__steps = 0 #determine how processor intensive the algorithm was
+
+        #when searching for a node with a lower value
+        self.__minimum_node = 250
+        self.__min_node_location = 250
+        self.__new_state = 1
+        self.__old_state = 1
+        self.__reset_min = 250 #above this number is a special (wall or robot)
+    ###########################################################################
+
+    def setRobotPosition(self, x, y):
+        """
+        Sets the robot's current position
+
+        """
+
+        self.__robot_x = x
+        self.__robot_y = y
+    ###########################################################################
+
+    def setGoalPosition(self, x, y):
+        """
+        Sets the goal position.
+
+        """
+
+        self.__goal_x = x
+        self.__goal_y = y
+    ###########################################################################
+
+    def robotPosition(self):
+        return  (self.__robot_x, self.__robot_y)
+    ###########################################################################
+
+    def goalPosition(self):
+        return  (self.__goal_x, self.__goal_y)
+    ###########################################################################
+
+    def run(self, prnt=False):
+        """
+        The entry point for the robot algorithm to use wavefront propagation.
+
+        """
+
+        path = []
+        while self.__mapOfWorld[self.__robot_x][self.__robot_y] != self.__goal:
+            if self.__steps > 10000:
+                print ("Cannot find a path.")
+                return
+            #find new location to go to
+            self.__new_state = self.propagateWavefront()
+            #update location of robot
+            if self.__new_state == 1:
+                self.__robot_x -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" % (self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 2:
+                self.__robot_y += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 3:
+                self.__robot_x += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 4:
+                self.__robot_y -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            self.__old_state = self.__new_state
+        msg = "Found the goal in %i steps:\n" % self.__steps
+        msg += "mapOfWorld size= %i %i\n\n" % (self.__height, self.__width)
+        if prnt:
+            print(msg)
+            self.printMap()
+        return path
+    ###########################################################################
+
+    def propagateWavefront(self, prnt=False):
+        self.unpropagate()
+        #Old robot location was deleted, store new robot location in mapOfWorld
+        self.__mapOfWorld[self.__robot_x][self.__robot_y] = self.__robot
+        self.__path = self.__robot
+        #start location to begin scan at goal location
+        self.__mapOfWorld[self.__goal_x][self.__goal_y] = self.__goal
+        counter = 0
+        while counter < 200:  #allows for recycling until robot is found
+            x = 0
+            y = 0
+            #time.sleep(0.00001)
+            #while the mapOfWorld hasnt been fully scanned
+            while x < self.__height and y < self.__width:
+                #if this location is a wall or the goal, just ignore it
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal:
+                    #a full trail to the robot has been located, finished!
+                    minLoc = self.minSurroundingNodeValue(x, y)
+                    if minLoc < self.__reset_min and \
+                        self.__mapOfWorld[x][y] == self.__robot:
+                        if prnt:
+                            print("Finished Wavefront:\n")
+                            self.printMap()
+                        # Tell the robot to move after this return.
+                        return self.__min_node_location
+                    #record a value in to this node
+                    elif self.__minimum_node != self.__reset_min:
+                        #if this isnt here, 'nothing' will go in the location
+                        self.__mapOfWorld[x][y] = self.__minimum_node + 1
+                #go to next node and/or row
+                y += 1
+                if y == self.__width and x != self.__height:
+                    x += 1
+                    y = 0
+            #print self.__robot_x, self.__robot_y
+            if prnt:
+                print("Sweep #: %i\n" % (counter + 1))
+                self.printMap()
+            self.__steps += 1
+            counter += 1
+        return 0
+    ###########################################################################
+
+    def unpropagate(self):
+        """
+        clears old path to determine new path
+        stay within boundary
+
+        """
+
+        for x in range(0, self.__height):
+            for y in range(0, self.__width):
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal and \
+                    self.__mapOfWorld[x][y] != self.__path:
+                    #if this location is a wall or goal, just ignore it
+                    self.__mapOfWorld[x][y] = self.__nothing #clear that space
+    ###########################################################################
+
+    def minSurroundingNodeValue(self, x, y):
+        """
+        this method looks at a node and returns the lowest value around that
+        node.
+
+        """
+
+        #reset minimum
+        self.__minimum_node = self.__reset_min
+        #down
+        if x < self.__height -1:
+            if self.__mapOfWorld[x + 1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x + 1][y] != self.__nothing:
+                #find the lowest number node, and exclude empty nodes (0's)
+                self.__minimum_node = self.__mapOfWorld[x + 1][y]
+                self.__min_node_location = 3
+        #up
+        if x > 0:
+            if self.__mapOfWorld[x-1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x-1][y] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x-1][y]
+                self.__min_node_location = 1
+        #right
+        if y < self.__width -1:
+            if self.__mapOfWorld[x][y + 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y + 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y + 1]
+                self.__min_node_location = 2
+        #left
+        if y > 0:
+            if self.__mapOfWorld[x][y - 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y - 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y-1]
+                self.__min_node_location = 4
+        return self.__minimum_node
+    ###########################################################################
+
+    def printMap(self):
+        """
+        Prints out the map of this instance of the class.
+
+        """
+
+        msg = ''
+        for temp_B in range(0, self.__height):
+            for temp_A in range(0, self.__width):
+                if self.__mapOfWorld[temp_B][temp_A] == self.__wall:
+                    msg += "%04s" % "[#]"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__robot:
+                    msg += "%04s" % "-"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__goal:
+                    msg += "%04s" % "G"
+                else:
+                    msg += "%04s" % str(self.__mapOfWorld[temp_B][temp_A])
+            msg += "\n\n"
+        msg += "\n\n"
+        print(msg)
+        #
+        if self.__slow == True:
+            time.sleep(0.05)
+############################################################################
+
+class mapCreate:   
+    ############################################################################
+ 
+    def create_map(self, scale,img):
+
+        # Map erstellen
+
+        # Img Objekt
+        #cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+        #success, img = cap.read()
+        
+        #Karte von Bild
+        #succ, img = cv2.imread(2)
+        print('Original Dimensions : ',img.shape)
+        
+        scale_percent = 100-scale # percent of original size
+        width = int(img.shape[1] * scale_percent / 100)
+        height = int(img.shape[0] * scale_percent / 100)
+        dim = (width, height)
+
+        # resize image
+        resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
+        print('Resized Dimensions : ',resized.shape)
+
+        gray = cv2.cvtColor(resized, cv2.COLOR_RGB2GRAY)
+        mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+        mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+        mask_list= np.ndarray.tolist(mask)
+
+        #Markiere alle leeren Zellen mit 000 und alle Zellen mit Hinderniss mit 999
+        for i in range(0,mask.shape[0]):
+            mapOfWorld[i] = ['999' if j > 200 else '000' for j in mask_list[i]]
+        
+        mapOfWorld = np.array(mapOfWorld, dtype = int)
+        mapOfWorldSized = mapOfWorld.copy()
+        
+        e = 3
+        #Hindernisse Größer machen
+        for i in range(0,mapOfWorld.shape[0]):
+            for j in range(0,mapOfWorld.shape[1]):
+                for r in range(0,e):
+                    try:
+                        if (mapOfWorldSized[i][j] == 999):
+                            mapOfWorld[i][j+e] = 999
+                            mapOfWorld[i+e][j] = 999
+                            mapOfWorld[i-e][j] = 999
+                            mapOfWorld[i][j-e] = 999
+                            mapOfWorld[i+e][j+e] = 999
+                            mapOfWorld[i+e][j-e] = 999
+                            mapOfWorld[i-e][j+e] = 999
+                            mapOfWorld[i-e][j-e] = 999
+                    except Exception:
+                        continue
+
+        return mapOfWorld
+    ############################################################################
+
+    def scale_koord(self, sx, sy, gx, gy,scale):
+        scale_percent = 100-scale # percent of original size
+
+        sx = int(sx*scale_percent/100)
+        sy = int(sy*scale_percent/100)
+        gx = int(gx*scale_percent/100)
+        gy = int(gy*scale_percent/100)
+        
+        return sx,sy,gx,gy
+    ############################################################################
+
+    def rescale_koord(self, path,scale):
+        scale_percent = 100-scale # percent of original size100
+
+        path = np.array(path)
+
+        for i in range(len(path)):
+            path[i] = path[i]*100/scale_percent
+
+        return path
+    ############################################################################
+
+    def calc_trans(self, x, y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+###############################################################################
+
+if __name__ == "__main__":
+    """
+    X is vertical, Y is horizontal
+
+    """
+    
+    Map = mapCreate() #Map Objekt erzeugen
+    
+    #Verkleinerungsfaktor in %
+    scale = 85
+    
+    img = cv2.imread("D:/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/karte.jpg", cv2.COLOR_RGB2GRAY)
+    #cap = cv2.VideoCapture(2)
+    mapWorld = Map.create_map(scale, img)
+    height, width = img.shape[:2]
+    
+    #Angaben in Weltkoordinaten
+    sy = 300     #X-Koordinate im Weltkoordinaten System
+    sx = 200     #Y-Koordinate im Weltkoordinaten System
+    
+    gy = 700    #X-Koordinate im Weltkordinaten System
+    gx = 240    #Y-Koordinate im Weltkoordinaten System
+
+    sx,sy,gx,gy = Map.scale_koord(sx,sy,gx,gy,scale) #Kordinaten Tauschen X,Y
+
+    start = time.time()
+    planner = waveFrontPlanner(mapWorld)
+    planner.setGoalPosition(gx,gy)
+    planner.setRobotPosition(sx,sy)
+    path = planner.run(False)
+    end = time.time()
+    print("Took %f seconds to run wavefront simulation" % (end - start))
+
+    path = Map.rescale_koord(path, scale)
+    #print(path)
+#%% Plot 
+    #Programm Koordinaten
+    imgTrans = cv2.transpose(img) # X und Y-Achse im Bild tauschen
+    imgPlot, ax1 = plt.subplots()
+    
+    ax1.set_title('Programm Koordinaten')
+    ax1.imshow(imgTrans)
+    ax1.set_xlabel('[px]')
+    ax1.set_ylabel('[px]')
+    ax1.scatter(path[:,0], path[:,1], color='r')
+    
+    #Bild Koordinaten
+    imgPlot2, ax2 = plt.subplots()
+    ax2.set_title('Bild Koordinaten')
+    ax2.set_xlabel('[px]')
+    ax2.set_ylabel('[px]')
+    ax2.imshow(img)
+    ax2.scatter(path[:,1], path[:,0], color='r')
+    
+#%% Sphero Pfad
+    pathWeltX, pathWeltY = Map.calc_trans(path[:,1], path[:,0], height)
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__init__.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/GameWavefront.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/GameWavefront.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6ece39f995948bca62bb749c1b4a8dab486ff1e6
GIT binary patch
literal 8672
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
JBg<>1I{;fbUk3mH

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/WavefrontChatGpt.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/WavefrontChatGpt.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fa1580cd086f8ded4733863dfce1d64fad32f881
GIT binary patch
literal 2682
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
CV3y7R

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/WavefrontPlanner.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/WavefrontPlanner.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..69ecb8c18f678b45bcd6677f7b077115e6a96516
GIT binary patch
literal 8584
zcmd1j<>g`kf&67DYL*NPk3no?%+A2T;K0DZQ2d3Ffgyz<g)xUA3PLkRF@gEaxhzqv
zj1V!lC^mP76s8pB7KRk&W~L~1cZL*}6xJ4o6xL>@D2`Ol6t--pq92?LsT|D=QCunP
zQQWBv3wTmEQW>&%7cxchrE)FcPvuVKTgVh8kjj@On8KLC*~%oz5W^HD6eXO(6(y3w
z9VME=6D5|y8zr8~wLl_OG*u*3JXI`}dm(EKOO$AoNR)V#SSs5BwuKB)lBw*e0?mw3
zQmIl4q(Q0{GBGlwN-dB9>4LIlQ}`A#M#({S$fqi#@TbbBN=h(@F*GwWGNf`XP)wCe
z<zC1XC6~&uKq(cZS~-<<fyzRVt5l=ZQq>lyrwA+rsa0E`k*W-3X{HE5Sz0hwmUgOK
z3S$amD^m(X8j~agoF@e0r3j~p^fEItz|Gc)(oNM}pq?TMHb-{>%tYM<FcWnbXn@?q
z$dIawWH#6|xY=Nv;AV3z(1XihQI{&TkU54aN<YdVg)x``gf+!pg3^OuGKfUR%&?S^
z#K6Fi$`Hkv!VtxjA`Xsy#wcb;yhpL5u%)oKFhsGYaHMdyFhsGXaHVj!FhsGZh^O$R
z@U}2UaioZ+@TKs#Fh+5v2&4$MfYOCfif{`<6nBb9if9W%6i<p+FoUMVErIgHvQ)RC
z{JfHYoW#7m)FQWJkRxD@0<l>b7#N&E$@K&S149i{4MRLb4Py;MJYxw{33Cl&Gh;L3
z0+tlUg^Vdo*~~>!H4IsdS*$T2b!;^Z@$7m0B^)5JW=05|!Ys+q%*X_nPhqZMi04dU
zsbPrcN@1;Gi04iL>ElUfs9}ibO<}KLi01>V;RllfDI7Hn@q#IwH4O1WU=d+3DFP-%
z!K7FUR}DkFIGB_Gn<)t<rNAQ6DGb33n%sW3So2DA3o2j!|NsAg5hDWw!^`K)3=A(p
ztXnJrjv*c||A7QKKm;d<_{G4$peb`pJRUvF;^T{R^2=|@Vv)#AEbvbY&o9bJxy4*u
zQgn-@q_QCO7E4-YUdk=j;*7+C)LW8Rv}L4bre~DglE5NWo|#gTaf>-8HSd-b7U{hF
zl8nr}bgZr{Pt3`|Dv_R_h+U!}u_WV`3>ItBGV>C10zk6Z+*p*KlwX3?d0?6N3OsU^
zSOWy)!uSf@QrLBsq~;dHJ7U!ZmU6=Cj^zB(ypq%+tf60Al3GxFOCC#z<Ywk&=9cEh
z=jErQ-crG?04y1wlb@Vel9``}HDL2n%j1hn5=&CC%I4>!;E^p#Elw?o&&|x!WWL2x
zoSKt%iwi0Jv49fkN`@kB1_p*-)%qFvxvBc4Nu_xurTRtr#YXYv#rm0f#U+V3Ir_x~
z8L372Ad@oVlk@XRit=-EQj7F+GL!TRDoZl*^NjTj4fKmMOHy?U5|gtN(^HFa=?PCP
zOHD&6U-SwpZ*j!OXXa&=#K(()iWLI}1_m}pHbyZ<AtpH{HYO08jggIsjTy{lW@BUn
zVMYYa#aJbYo(J_{W@40IOwjV{vjC|40+n2lQj8H?6f;$sa4A4RaB4}hLP<ud0yveb
z7b_%}78RxDl_(VC7iWTEj0>*RZzWTaGy?-ekqiR^!%F5N4F(2=TZ|RA7%Rcy3n6qs
zf&#^<B|)J45CApAj)8&UGpJByW8-41QpE5Gx_X=*D$)ZLNK92)a96=S0Lm_KSL>lV
zTNdPOIS>H~d5B9vX`%@1T>j$J68HSX9GGi8KnhJ57#OM)u(=djX)>tjgw-4%Haz5c
zKq1eN#Q>@Y(wKr7Rx<h(>4O4}5gc&nZr}xnKg<O|pzs12#lu)7hv5bkr8r$sWDfF%
z1&A;O5tbkV>}fCo_BjtI&|sE^ffQJSye*4iC9=9?ki%ep21P0egKNuKj0_Cv47E%(
zP=8B;e9r_XnX{RTHq|g>v7|6&vlK~|u%<A9nnfwh!3;GFphgy`-mGEBVozboW-79;
zVPIj%VoYJNU|?d1XRKi?GAm&P)n{3ZH4IryX-tqtRSnYua6JnV12u2JCV(1;31AbL
zQdrDECNR}77KM{w0(&-7Q6ty{MyLrOH&l>d0!KDe(IT)3Oi*8d+%S`P6F@Bl?BQ6<
z2Wkmqv4}C$GS@JJ>h~<J8ip)xP^g%L#2AZCm$23_gTl9lVFAxV21bS&CQ$uf6#>sS
zAsML(sd*(ul?ny<nRz7&Y57HnVn87=Cq2I?vm_%|p(J0Sv^W)<55Ps5LP1e}L1H?%
zFh|N{nF8tz3{}F;iFtYXB?_RbULjEdRFmrY6|sSml(27pSt`i13R~3_g-To16fUlp
zpoH`i)ZTgtN<vjKZuzBoDPU)S(wjnNo`Pzo0=W9I;;NEBl<Nw`nN_K_AW79sE-p>p
zB3@9^g_li5;vlXPs3c-7D9X$$xg`X1bt=4UE>Z=_vn3W3q~@g*seyC|fe2xcFb7zh
zZ(@Na3plslVks!fE4jr2^3g5k+~Rcf?8{tKnimBs*<BbI7+BaO7`YfZ7+Dy(n7Eku
z7+Dxa7=;+Q81b<<7$u%^$%rtrFmix(R*7Kb!J^VUl&l8|S5UZtvtAk_11KXgfFqj$
zl1*wDvY5e{kHrR*5kb`eYYjsd8z{SgG74CZ!-gS+v6iWZDTOJUp=e_YV=Z$EV=YS!
za}7flXEsC8lp2;AhAb{Hiy@1t24o@&SSNQjb5R-CEQA;vL~H?14Ra04LZ({Q8jy{=
z*$hQ#Xet@AnTpbC7>kli_)=g=l^^PQ0Z^fkC0N6d#S1YnOE85+9OMV6{Wc6WETD{8
z%K~*BQ&AVx#mpcUSPq9jiVbQQix!perLfj8flP%KB@7FowzDu~34!!8F~kdjRG5Pb
zG;rt?D}k#|Ha|$y8PqqZ5^>AS%Ph`FO;LcSEGw=eP}EfM1ed3#7APoNDX3<0X$s%s
zF3p1{!y+kAT0={=5+E^f+C|h?@HANjYB<~y&&|vWE-fkoWt7akbie$R)Ud>y($pe#
zkX}#^y9ksVic~;cWe@?%2AXW(R9xf&O55zvwqB7TNZJS_#Fm?x=aZj|mZ*yy85kH^
zVTqc9QG^MEK?#%vl%$zOn1mRa{_`+%F@k6oCQ!m<W8z^FVd7vC0ViUS*DT@!j2w)7
zphW$EMX^d5BT>Uc1Ri`S6&k2;V1+hjic1(67)lsYKve)^Gm{HLtYIx9l+Og_Yk;dB
z<{Cyxh8jq<!;;NhWCqFyNMfv5#6am5q>de-)`p>wuaGSTRB$p^g~AKY<eb#RqGE;o
zoD^{R1}f50QcF^cax?Q%74lNc!J=^0#U+WA3gwxg{)s{oDAE#(DiKW+a60nS<haFJ
zl$e*ET7-yfaLNG1IHW8Crwmb0d|_$76nQc*Fl+?H6G(#qy8yVjVfrt`#Pm;qg{gt*
zH_QJj8H|ueN{txJEl{w7(ot~|xL5(TVnDSpC<~`BN-$(I6d6DQDuq#;0Up?lIK)Ab
zfJJ>gV+yE8%v!^k!ko=g6bUm?0@Xxp;vf^Th{rR65=T5MsK=hg26bsG#9WXop{`}f
z0=X2MILKTq;_-~&zB;JD0J(G>vWZ~VLQKRa4l)socswJhH4_gi92tWdG})?B;Yp?>
zBePf`H?<@qKSd!YKR>%zA+bauQ32G)Qb^28Q7B3+DJ{x_G}?3W%TtR>6v{wFfI=d;
zR8T0%NGyRH2GWI8O@j-jB2a4_ob-xpK}pIU)TCyIlpx?D1Dp)ODG;3Gz-0-jS}ekr
z_`Dbx7!HCGAE?31!NJEQ!6?Sa^k0OTjgbS!W@2N6i!-5$voTg_U?fc(g&a!B0IK;w
zql(~UdWV4lREvR115o1=Qabq8GL<l-fcTKo!KoHhr!j*|22hQ~kOgXLDua?=3X2$n
zIYTXDp#V5)L1hO-1#31_kqKA@D-IQ)#-=M+1shxiV+wN#q$Giw)Xaz^#}2lMqlPgB
z%qrmk4Ja{!YB$alP_r?oglhqJ3MZ&Jo5B^$0K%HwRW9&24FEN1iWTxpOTbN~+{6Nf
z{4@n{vH^Ey^O92`0;vkgIf=!^Nb!G*0UYmDEUE@3#Z}DF%CWx~b#F1cS21yMg{04#
z2?8ta{WN)sd_gG#oDje<4^9oB;ssK1fh#FKkP>i}1M2JCVkybYO})ihoRgXgYc>_R
zfom7&xC0xQc0{jbKoR&1lz<e#O(y|HQ2E8jD8dNAGEAVR6bB=?A@v_iCm7aL^V4K>
z)8qwpwDS^kQ{&@ramB~y=BJeAfY?0o@r9*{IS`p5U69L-L4+BIumTY_Ai^C)fT}%k
znOX!&+mQMc++{)#pw3efsPzg8mts)3a4>Lja%gaHad2_4aItV{bLemg@Th{-U<`SJ
zG=jpd7-S55$dfUJsf8hmIfXferG+7iC51JG4Lsn<p27hh@Z=0;(B!(snVVSPT$Gwv
zl8RDj3o<Y;aKq}!Z;a4-k|~R^nTZjU2N)$7YMD!zYM8PZL4%Ps%pwdaOwtU^jI}IK
zQBa!>A<A0AQp1|YRLfSvoW)YZR0E<}Q&@YMYuQT}QrK$PAtskFFJP--FJaDNU&vI;
zQNp}{qlTk|a{*ThdphGnMlg#5#9GK)%bCKG&RD|%v0sD%%4U&d5Mik0D&frHUcghs
zxsb7zyM#A|rG_($F@;5v0bHx|*7Brqrf{_|)Nt4ENHVxEG&9z4)$rIb6sDGNW^vVU
zl`y4n_cGOT)o?A~TgXt$o5EAe2R4NZ$&`Xx9=I52I2P1?NUh}ui}8W&iLDi=3aa4+
z*-^tU$&kXE%~bRzg%@O(Bts2<4WBrJ4FiM^VuQpGd~h|u595R6YWO5D)PwZF)PUHS
z>LBKT<Php$Vj%Ov8472zFqH6Deq&?+!AOR}ndJ<HlL|X(xPlop`TVNH{EITvGxHL2
z6kIZMQ}c>5^Ye-otQ20RfYLUoVG1q+G#PL4W`c(N3i5Nnow+K}pj1$|Dg{j&s8{py
zKLY~;O6dzq!k`j37?g2A<3XUI>sYQ@#u~;HhHRE1t`x>R#uTQBOoia~QxRxL<rcH0
zrR6PV0|Nta5unL*i%HMm7GoBe2O&Ti;ue=pPG)gQa(-@sojfB0LovuM8HOqic*@sH
z24{fy+{6Ms8_>vNPO+UHLX#%rE!Gs!m@}lJ12rEt1&Tl!t_YM(ZZU&;gv`lhMz`3C
zz+S$^<>?pV8Wiss<mz~fBe|@^IX@@A=oX)|zmI=Ve2}}7k$aG1<Sq8hydY3B?G{sB
z!7bLrqN2pgTkLr$5C&UGKFHPJa`P5Ta(+SOEl$^p<kW(a%=|n}L2&!~7He^GVovHU
z=FHsmTfAU)d_ihaa%x`5Emp`FHyd;moH->k_ZB<Ec`3J8(m{5y<R%tp7iofuR89~x
z9%SJy#>`v%h@Nq9W>sp+EymQM1duYuB1o`;3oc05B7%+y6t<vv;o;(75@Qr&<X{wH
z=3(Sxl4F!%;$akFmSE&#;$UQ95@7<B#Y~K#k{N<U7$K0QfrpWWk?B9vSEm0g{8b{@
zVkjAu<Y1#kpb8t5Y(QmxaR|85u3?p6sAVew&9AVDFr+Yo3nj)9(0C<+&s4%t!(4;l
zGnX*bupseSY8Y#nKwZu>mSBdJOnya?pf(L-5vb_ZWQPPkQ*p&DrsB$5Oz9Q3n9?hY
z3PAax2t<H`2TXv&h#L|!+4=cJDVCr>0#$Dui~>v$&+{-<i6T6Tq!y(>2BkW<PeFA{
z3S$iuxDaMoz*xh$kg*nNF3E)<mZuiv2Np?&6h;w-8fIxwc(B+o6!O<F1~U}ZgS^91
zlm&8aHi!UM&mtgER<Q4iTtT7;FI9oKU@w6Qu)lbVQjuKi0`eJX(iT*;3NVQ=vM^PN
zBm9M;HW}m-SR8`l6O<*vaR_ok4KvthEH#Ya?mi1>w6h32?g+9Q*7t<>Hj6;rxLa(M
zAw`LK#kbfhz%*t$P0UG-F99j>2RRgEDQG~2g9#;-!4>&wvKNJd{0tt%3<t65Ktv0O
z0QF&uIzTLtgV3xhieO-10F`gW;J{$uVCFFA;O5~5i-TGdxrv#1@$oM~rdPSSSivU_
zii?tQO#tASOUO<vDoNGLDo6*nyEAnd85qC?W9A+v28Nd(7#JAbs<cD$^RpFH(-ewR
zlk@XZib4I$qS8F10l4DK+)`+fEfP?apI(%ho2%drO01cAi6yCdRV>j36|s<(ek~}4
zFy3NK1{G*k0#2DZDacAS4U53F0;szOPF%MHa}!Gna`H=ZGL!TQDnYDUY*3oHAg81#
z5EP1_*ars>ILL1?`z98EbJH!h%-o{X#FU~8kg7ru0g8lM9Jz@F;Q2ss`3sK!qGFJ2
zBZz1K5zQc?2}FQm>=tWrNn%mSE%pM)1Z@$xnFemKfm>*x#D0qzG;Rkj)j{!lixZq!
z3i69nZ*gSirh`+}Eso;SB#<YHZ?R|QrU&HYm)v4btT4RA37Rx2$t=l91-ZF6BftC>
z7f7fgCow5C2g0s|u-S`~6H7o-V<1yOCK!Q?FaoEiTb!T)!SK|ak_ZGd5-EX!(;GPR
zao9lGqIRH30&vmC!Op?R0~#D*VyNdU<_KqEWMgGv=40Yv5@KXwW?^JuVquhG;$Q-)
k;sK8*3NZ38ak21#Mim*k7`YfV7(s(CAQp(N$INmP078i#%K!iX

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/__init__.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ec9298825be9e809c9848ee863fea5c84f958e7f
GIT binary patch
literal 208
zcmd1j<>g{vU|?`?cT54%k3j@7W&}wxFfbIeFfcHrFa$GbGWxA#C;|y1h+oC}8Tq-X
z`lU&wc_pR#Mft@>@#V$(nR&$}i8(p?#RVCuMfvf$nR%J<$@zIDMfo{7sYUuZnMwKu
zl_eSZdB%E%2KvRBC8@dviOJcC>8ZuI^u)(!=4F<|$LkeT-r}&y%}*)KNwotxrkII=
Ifq{hq0410>zyJUM

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/_constants.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/_constants.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7445d8092b0df51dc16b0e6b2f448a1c3754da6b
GIT binary patch
literal 2315
zcmd1j<>g{vU|?`?cT9Q1%fRp$#6iX&SqBCNhT=&K3=Am@Q4A@JDNHHMDJ&_hDQqe1
zDI6)BDO__nqZm`TQ+QH%Q<ziuQutE@=CDOEr3j`7r3lYqiegR?NfFItjABXQNfApC
zPmxHGoWl~u3f3W&BAp_W!k8kSBAX&Nha-v&Y>Ie_Sc-g#LW<%XwkY-#?i8^UrWC#u
z<`ktA<rLNwg%p)JoKYMps=*AJYKi-p85p>{^YY8{6arF<G7B<NixP7bLPI@Wiggt7
zlS&dZ^HNh3k}4GnOH+#~GxO3FN{c~cNk*!IQ%-4WL8U@&eoARhsuh<lH2{}mUP-2c
zi+`|!b4FrOVsc4pQD$*TX0n2ffq{XMfq{XkuBo|6nyyKjk%6wMvAKb+nT46Dxsh3#
zk)e^H9hXyLNl9u^rGigtS!xc387Q)LTu43+C`wIBEh<V)QE<-B%S%lz$;{7F2uLhS
z%uOvxEh@$^iFmDcT#f;r3SmYVMi>|v7=k>7-$O2Lp&%!f6y;-j2c#Q>@tfe6n45}W
zxl3wUW^$?mNY0MSv7jI|u_!Sw8B-lX%8m=<6wkc0d<?@tZZI$~Fv0JR;M5|poz5AF
zdFh~lMvGuHc{{GqylhayG{j|}F@F1?+HnRv0qtBN8L0|Isl_D<`DqHE<X)DTQ<_?=
zP@Gtnnxc@I2Np}o1gDh5qRiA{g{0J+{Bj+I^3<YKg{1tVqWtpI6os^+{9G=F%=D!E
zg3MI)Vuh^4vc%+~%z_eyoXn)6#G*<ah4PHd<P3$(Vui%A#LS$;q?}ZR#1e&!l9GaA
zD}DX+%#w`KB)#PPTz#l1`o*AZnqOw5msQNg^-_R=f#Ibfh!6%5Vjw~sL`Z-LNf03g
zBIFqu7&JL=@gx>x1{CEdrxq9I7v172t}HG|%>_m4EzW}c^3)<QlRc#<vn(?&{T5GR
zUS@7$Nl|`YW^(Z@w&K)0kS@;R{M^)%43Gl0(&E%2Pybsya3RM4&zGP=@FgS2RyGhJ
z1R^v*_Osm*%T3J8b1W#x$xKcJ<+8BUqT<Z_yjy}v`S~R|`H3m1MNpw4kk4*$!3{P-
zVw)kc&0qF{%)bFLpXnBFa7kiOiGNx^VsdtB$t`Zzyc9TxJuxT8$JM3yB_Buw6Nq2|
z5gZ_`EVsBai-S^&3-a@dQ*Q|rr52W^7MCDIBw-@{c{!D?MMe2VaK++9sl}-!#h!VI
z$t9U(nI)AWnYpR?r6n(!L8kM92v!gw2eOCb7H3LoYC&*LYHGnP)?zTlmjo%d!t!%U
z64O&}v6Lrfr-J=o1d2N(&l)4KO<uBtOyvQY%65yRD6!l(za+ot77y4t9;t~bpcvu>
z#bv5vaWFX5+~S0CgOYCvfSKW$B^hwF#U+VJnK_wN;HY^i0y3T-WIX3BE=b(_CKhMk
z;)Af^{ufHl&r8cpFD*)S&d<ro1jnaXGK}exT9TSvlA7XJT$z^)b(~Lraw5p7BB^<x
z1P|8+QNs=~-|!ZcVRTCrZbL9Q2?m!Gr6%V3X>#6TkB?8uPmYhj#gPIo(>z^n2?fIw
zwR3)MZem_a@h#!v)Vvf(nsCm~D=taQD=EGu07<-1MV>Cjw^-A164Q%s@q@Dhk~lvo
zs50}?p+d#5Ab{~#G86?cFhGc3rTQ89xvBc4Nu_xurTRtr#YXYv#rl~bTXS-txi>yH
zGcPkfIX@3nvgf20>E~o7=@(R%WaQ@=>lqs87iX5F>J}s>XD6no7UR+b(hu>9UP0w8
z4jV{SYzNAC#aRpt3@i*xB20{^knIN(7ea*XHxoM(BinxtW+o<xDBE8qRtO75vi)S@
Qgt3_zAvzFz5R2;v0L&rbi2wiq

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/a_star.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/a_star.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..08bd874229860af63cd5c26676a69f05c506eb88
GIT binary patch
literal 7276
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
M5zb-2#mMp>0DrlI1ONa4

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/blobErkennung.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/blobErkennung.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9a67c7471a3ce7a50008d13c5d01bf261017add2
GIT binary patch
literal 1182
zcmd1j<>g{vU|>*7SeByA&cN^(#6iaF3=9ko3=9m#T#O71DGVu$ISf${nlXwgm0<yM
z3e!TyD3(-)1*{7hqS#Uy7O*d5h~h|LPUVQ_Okqjoi01;cxl>qEIpTRz*it#-dBGxl
zDeS2n@%*U_3j|U*7BWV$rLrs#T*wf^6eScToGP3plERq6(aIzV5)q9OOW{o6YGH^H
z=VU-p$FM*mRXCL)OL8GolvFC)0_jw#g^W=$sWL7Mu{=?-sj^veDGZVfQSx9Gw<JT9
zLSc9+!ve)rsZ^O%rUgpr3=0`kcv2a%lozr_siZP2P)*@YRawZy$dJmgKrMxDA!7=Q
z14F8M3V$<WHd9ec3S%%sp|hsIOHe5Jy<}lvU<i5npMinlr3i>P!N9<f4w7PEcwqmM
ziGhJ38AL!t7#KjxL40RWkb*RnFw`(gFw`>DFw`>FFxN1pF$FVdGWuyU-eSv0%}mcI
z(PX*BSaFN7@)lcVNKs;5@h!FrFujtYh=+lJ;a7!zMt*LperZx^UP-BbQGT&ee0i~c
zW?pegVor{JaY06EQGR@GW?p7|a(-S(QGQNNYLR|UW|DqEWl2VUp0S>xfqrpjNvdu^
zVsdt3dTKE)JxMwFNv=iNsd;&&dFgrumAAN(6LXT|OF)h?0(pmxfq{X8k%f_isfZ60
z6pRcE44TYEAPPb-GcYjR;`C0fEXdEyD=B^nN_n>!3pF)vF(;Q9-D1rv%`K?B#gtcY
zizh5IB{knUv7n^1DD@U|a$><Pq2SEif}B*Roctu0)RNTXlKi4u94RoCB&KY9Kw?p1
zZt*R)0tn5UmYGwMTI5veoS&0lbc++@9|)5NCgWI?ns|#nH!}~)NUQ)e_+j#%d8tJu
znTfafb2Iax?4ZPw%=}x}tWPdVO)N>h#Zr`-m~xA~xHLIAwYc~eb7pS(E!N_U#Ddf!
zP~N)5TArCwk^v5}TO7${B@id^Is5zg2gL`uI~lnLIY!=MNiRyQyu}9b?=8-3SQy^o
z$WE;c00rkQrh<|p4h9B>B2G{+^QIIfmcxVk7HeV=$N)8$Ajj}{U&jz<57*#$Hy=m$
z;CQf5kf*apytiv)fWN0-NboJe%-s0$%#w_Fghgzbxy2dz<+s?&6EjP^Q!8&V=NF}b
zlOPho3$mKSCO1E&G$+*#6!XOvpj5%k!N|qJ!OX$T#?Hpb#>~dZ#>mFY#>mCY!z9GW
e!NkPI!^FqP#mvFX#mK`b#m>Vl#>B$N^a22ZfK!41

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/core.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/core.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0f0d8bf82de3f38133e759720cfe87e1591b9d40
GIT binary patch
literal 18927
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

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/dynamicPathPlanning.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/dynamicPathPlanning.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..783f7aad7b95b157db735ab8cb5f819656e8d116
GIT binary patch
literal 12309
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
b(6FosxNL^7K#OU3APZ}lBp78t^}!SX+<{^@

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/map.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/map.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..620dd53b562bd7e966028c25d4cf45bea0a723f2
GIT binary patch
literal 600
zcmd1j<>g{vU|?YTTAFf}k%8ech=YvT85kHG7#J9eXD~1@q%fo~<}gG-XvQd}RE7o2
zDNG9)qgYZ|7O*a4h+>1#F-%eHQEaIU3pi5QQW>&17cxb0r7|qwPUT8vTELUSoX)tA
z5zJx%u@*8%@usk*@}}~puw*mYFr+eN@uc#mGG+0lu=O%6;7?&+$hbgYAwv{z3I|vf
zCs>tWDsM9*BSQ*fFoP!7OOTuWsthwqN(!v>^^5ZJORPYIgQ0<*p^=52iJ_j6v89!T
zfqrgQLArifW=d+l9*Freih+UQ<$n+n&cMK+$#{!3rKGYT^%hgG(JjXCVkQO#hVXDr
zp<B$!Wk$DH^Gb6IDsM6672M(p1DWBRSWr@0lzNLfIkDgtOHpcK$}Q&1-1J-Q#ihx~
zsl~;&IFidsobz+?i*E5b`}_C@#Rs`N8My~JM&4pcFG{Su#h#fLl$e*EdW$u&2*hW}
zO)Sp7#afz~S7LFCr7SbG{1$t0VQFe=Rq8F)f}+g4l9dcaQVa|b;#Z!2Mt*LperZx^
zUP-BbQGT&ee0i~cW?pegVor{JaY06EQGR@GW?p7|a(-S(QGQNNYLR|UW|DqEWl2VU
zp0S>xfqrpjNvdu^Vsdt3dTKE)J-LYmdIgoYIBatBQ%ZAE?HEC6LX3fdfrFWYk&Bsw
TiHDhwQI3&^Ns5VwiH8XQ_NcI6

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/maperstellen.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/maperstellen.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d7213af60b65c5c312c56bbf5e7092116999e2e1
GIT binary patch
literal 212
zcmd1j<>g{vU|{&n7nlN~AA<;F%*epN;K0DZP|U)>z>vZa%%I8Wx00a<B#a<_mFs8Z
z=cekHCY9!ul<F7d7aPTw7wc!{6_+ID<meX{WTY15$LD6|WyUAx=am%Y=j5ao>E~o7
z=@(R%WaQ@=>lqs87iX5F>J}s>XD6no7UR;Bn^=%qR9upplardKS5SG2!zMRBr8Fni
O4&<O>CI$uu76t&7d^;)t

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node copy.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node copy.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ff02a86b8c9265a9299da6733a1150a03c43a61e
GIT binary patch
literal 4396
zcmd1j<>g{vU|{%l!9B%Rl!4(fh=Yt-7#J8F7#J9emoP9eq%fo~<}gHoXr>&-T&5@{
zMi84ZhdGKlg&~DGhb5OaiWMrx7R8prkiwF~p34!%0TyG;;mqZV;>zWY;s*2Ca(Hri
zqj<q=#vHyV{uG83_8fs+!6-qfm{63EJ3|Ub3TF#L3TG-)Gjo)13U3Nm3U>=*lt`**
z3QsmuQ9!ClGXo<-3S%%BYx2DWx!+Hd@fM3;eoCq)<1J>-+)_=(TWrB4MVWc&noPI2
z0!tH1Qj793^Yd=8hovT$<QEx()H&r>Xfod73NFY<Ez0-J%*#v$8HJ3Qp`2nL1_p*y
zhA74qhA5_XhBU?$#uTO&jwt37<`k9|hA5U4))clDhA7q)_7sj5hA6fa&J?Z|hA8$F
z?i8LDhA55{-W0wThA7T<1{Q`Wu3!dD{#$Iml^_QvGeYeEQ6M%e0|Nud-eLs?28I%b
zW`+ffDU1sl85wFA7BH1Cr!b{3FJ!J^h-XP*2xib^@w>%c4E8{LZf0I)5lH7tkP(`!
zw^)ly3sQ@2am2@G=4F<|$KMi2E=o--NsTWkP0GnE&PXjP0>$?&E;v6P6pY2GIcX~y
zZ*j)QC+8#<7sto1WcXF9pOK%Ns$ZH^npaY)UzA^L6klGfpP5%&l9-dDkK};(<ovvn
zqWqkk)FS<y%q0DS%94!yJYzjW1O4L6l2qM-#N_P6^weTpdU7k{(=v;SOXBnLQ&JU@
z^9w5V3Mz|u85kIZK*<v1ULHmf#wvbD=;^`yh7ydRKwx8FU~mR$2?M2M##+V_h8jjt
z;Po=qGSx6GU|h(+$WX$R!cxPO#XOrKg>^1-GboUm7O+5N*izURutHK}4O14I3qv#G
zLdMw)bD1FOf*CZq{Hg?<&8*BUt;~(AoL#J(oUP1UUV_}H$#{#iEVU>pzc{m`vP#e?
zwWK7qs8XRUKc^%yJ=IF#7GqhJkXvR^Zh2x+szO<6QE_H|9!OXZ#Uo6xv;gvm1Oo#@
zBSQ^CEIY(A&5U6Tj0}ZLpmea35tIX%i%W_$nQk%Z8Qfy5C=zC1V1N)J3=9mnIBn8X
z^HM7citN-trh#0^)F8%Cr3ekl<ovw6)Z`L9o1FaQ#GGO~J-B*J_970D34-aVB~FQ8
zpM*g?a*MT~C^N6*7F$_-QesKTEt#U!lG36)-^9#3$AW^K%;dz9%>2ACi1%)>WaVe(
z-4aNHdOIHKZB6DP0g&<BzK+iEjxH`iuED{#*dS>N;(oACz@A`-x>6kE1wIA_1{PKx
zW)3DHMh<2LMi#~@K2*;ngM10fSRl;Jz`y{?8Q@fL2Aa8QSxOieFx4=pFp4lNWGrD^
zzzkzEG1aoxvVmopkYu53CZ<~US`M%*Ba$qX&BRp8S<6+!S;H>EP{S(1P{UQjA;M6@
zCc+@jP{R_>Qo{w8;e^RZfMi%}Abf}(kZzbBHmGTAaMM^t7{GeiYgmFAG@1O;L7rq_
zcwn!|Q3UemEvCGJTg=J%#kZJ?GxKgSmKVu@f|;@M7GsqrHzdqiKw0$`Ye8m7a>gy@
z%Ea<pjD@$Dk}Gd96<6M3N-ns?R9tY2DY@ttQ*jY`TnIu-lR|juss)M_P(Ed2lmkO4
zCMiY`WMQh3fW-`?2tsH=i6fA^L5Ut5N3a60mZgTVh9#b{hN*@no~eYnhPfHUX94-U
zNRokpL6fxzl-<GpE7Asek~J+SKe41p2O<ehUaaY0zp|x6Jj;?^nOI%~N=NAaQh@p^
zF)zI|C$T8LEHytTKRL6cGQJE_cUXYD393ig7(tMWk%g&B9o2g{_2Tv|C~`o>J*sbO
zm}^+#nGrr^LGvk!7g;J2lap_;RD#K>#N=eG{*#3IFDElEHL)l@F*zCLF-KI7v4K3M
zfa)<!P0676f+Rf#1`wMQR`P<%nHt6{h8o5!#u~;frW(d9<{HK<mKw$^)*8kvwi?DP
z_7uiB9N^Te$x);WDzNlGgg%I{1QAvs!WKl>fe3q0gmT>C@bnFh2S+C-hy{sJb`TSk
zgt<VB^va_A_=;NycI7RwT99`u5KJV|DorMErYKSc*#s_gzy!G95lBxhi7!sgE6y(}
zj!#J}N%R7R6)3H<FtIQqL$)7P;?OWd*OLsYm|#H#Dw;sa9h}rlV8szLq-t8gw2)x|
z^FoFi<}8+Y)*1#-V5Klhf~znv$t=l`!qUrJ!yM0E!;r;M!<fPf7H5-W0JTBDGMqIG
zSzI-YDV$&#E-=Y0$&kVWmgNT38=Aa+Xu+<@j3!WohzC&fM3Wgwz#0@%XtBdwgeJfP
zZj{{O1cgR&PJVLsE#|!Z@>^^r`SH2M>9^Q2QWH~Bi*B(Nmn7yE6q$pvFL!=XW@=su
zxb`Tr0f`78aug&p7J-_nw}cVtF*PT(2&_Sq1ssjH_+ZghmY7qTT6~KI)TFq@n2Da>
zxuMOU_{`kWa8Rr&F)%Q&F^Vv;FoCi+8zaYG7FH083C?0;<oR1A1dU}R?V8-6)>d9(
zZfbn|Ew1?Z-29Z%91xo)KEALtF$W?8Zq5{eatGMAU=M=5Q{)K>&rpzmd7-VZ<kXy;
z_;@5I3xbq@l4KDmpMgrYVi3W>z{AAB$|20b$HB?LDZmSsMQKa0GcYiK3N3JY+rh}d
zP{m)uki}TTkiyu@2x<y7Gt@HHFoIHDEmJr{o)8N|2}`9SBSS4SBSRHi32O?Z;ltd-
zn8HxYT*q9_Sk6$wmc?EIPJd~Pptf)?b1h2^%K}bN6RL)B0aps^LdIIws>vk`3%D0D
z6dkW&%Hl}@wVIJJTQ3JALk-gcUZ^g<8m5JewQMzv3;1i;Y8V$Xfn>7;K<PS#J%zKE
z8O~=%@D~WCaDiLNObdikIG`-y6mBR>1Z+0b0>Kn!sEAMsJA?%`nH|*7gP6QPG=(RH
z9b)SOgbAW4>`0=#NP0PtTp^mmholN-J2t(n3&cQff`m-5RX9T)CksP~c;!V#1`v#7
z$ODBh!vYDAsv4FBk{}wKXZb;GJ(k3x^x`Tp@BF;Hl2nDf%;by`P&+ayGcP4IFGQ31
z7F$VTQF>}gQ4}aSv85!Y=H}<U1eMR497UisP~-$kNuVOX$Q{J;01<8=!UaUQf(THC
zfB7F&<}%-6E=o<g#hPA}nwocuB`K#g)$JvyID47Gz`*blq%d>N|Ns9rrEaknCFc}W
z-eLiDI>5;goYZe|x>h8o7J%A=Me-mgah7Bhr6#6i=B3|a3js54u@o0%=79@>qLN$O
z&}ynEu_W~tQ-1a>;pF_hw9NF<qSRn;IqaKQoPA3aO)$8mC^az`DI;+gr<VA*x;W?O
z<QLuIEiOq+%FM~E0v8mwgo{B9+T?5>R~OH`lGHp<WBnFOd17YCEuNy(;?xokhy%eT
z;w{$VoYd5UTY}!Hl}Y)DMJXUHMMb3rCAT<=GfGQR^2_szKt+cpJ2=dXf<Yk&s!MJ$
zrru(M`1TeH$U8+rASrO=0wzG&`4&rVVrE_usQk%dU|?Wk;$dWC<YDAv<X~iB<Y-{}
zC&I$P$i>LS#KFkI#KedS*?w?vb20HS2`~yUb1{M-NG%tm05cCGNSupNfQg5Zi;;(k
zi;;tg<1$MFk3I_{(|-<T9>$_-P;79-$Aj#TkB2m<#EMcuqFmsp)B_cqMWCc}izTZ#
zKkpVlq+|sZ-^F^l#p&Pzz9<8vgQvJ81tAWq<8BG2r{?FTmK0SY#6k5QxFK_kIVr!Q
z2vjuPV$CbfEvPI~2bm%VY5m88y0l0=O1+Yz)Xb#RB1m_HBPFpUwInk)6_Ut6-Y5cf
q_K*roMCfwZK+0k}P)Y@NtvQ%@7&#arSO7|MfWj|{!-b2H<v#!zTrh9|

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..248bb73e7affc7258d67ea37f5b04afb3cfde55b
GIT binary patch
literal 16367
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

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_alt.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_alt.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..06a366f1ce4b99ca1ddaf00017abd0a8c6868050
GIT binary patch
literal 7256
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
F{{SJtx#R!<

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_komisch.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_komisch.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c1e46cdc304f86d99a14af9101ff3d91dc2a4b89
GIT binary patch
literal 6049
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

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_refwinkel.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_refwinkel.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e43bbb000175664ea4762646b70442df7a02e31f
GIT binary patch
literal 5129
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
Qm>BB0tT@!U7+L-U0D(RHXaE2J

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_testfahrt.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/my_first_node_testfahrt.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..76054ad895508d64e1faf9ec5c48338bd50f956e
GIT binary patch
literal 4401
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

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/pfadplanung.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/pfadplanung.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9c01561f4863ce4dd3f66016afa225f0416bf5b5
GIT binary patch
literal 5569
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
bo1apelWGTQI~9Y9Q4U6idX^X#Mm|OWJQPa{

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/potential_field_planning (1).cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/potential_field_planning (1).cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7f6164b8357f6cfb2c910cd87d914c0b16dcb959
GIT binary patch
literal 4688
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
M9!54s0Y;X;0OU|V$N&HU

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/potential_field_planning.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/potential_field_planning.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..89654d357ee99d891520683d490f3272debfb4a9
GIT binary patch
literal 5668
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
AEdT%j

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/simple_moves.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/simple_moves.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..650d674336f70da01d14cf5aebb304a70229227c
GIT binary patch
literal 824
zcmd1j<>g{vU|>+LbW54d!octt#6iYP3=9ko3=9m#5)2FsDGX5zDU2yhIgC+^Da<J>
zEeugiDNMl(nygjTT)~;S1v#k-x%p+O#ay~bfQu_6BePf`H$SB`CsiRiKd&S)Gp|@7
ztu!yWBr`v+SfM0eAtSLYRiPv!RUx<_Bef`BAvZHGQz0c^p*TM`RiPMRa&Br~NwI=P
zs$RODLULwNa!#tI9@k5dgZ+{jK@=2&*sKf;49*~@A7fx(sA0$gIh_&Y{9a~8h8l(i
zj48|u8Nn>36c#9pIfWI<Vp+%lmSap|gNiVvFhW>RlUP!ipeC`Vu%|FCWCE*4n82FC
zh$PB^q?ZNB6|5<oNUC7AW6_(!5X_*-<yQpqnkMrt=AzV;Tde6tsi}FlSdwx|Q{7(v
zXJBA>$;`mO5b`nw#006#ob&(xe@(Vq+{LLSKCUj#`8oMTw|I+75|c7>GOH3n5pYYm
zIJLwnF*)1E)x|TfBsH%%v!wDCOL<~u$t|9u)Z)|<kJQAJ%)InlEJgV_Ihu^O*owii
zw34AnfPsPGSGj&her~FMX;NukNvVEOez8$}d9i+GUU5lcPL4iAZ9FJO<3W)RG9$G}
zKPNLuzo4=tBR|hr&(J`>II|>Gw;(Y&J25@A7?&PMLWl<^F};GyTkL81MdgV_DWD`=
zti-^;Ai%`M2!b47Qh=F<k&B6kiHlKyiHDJkk%x(ou}Fx4fkBh`7JGbrN`7*D{4M6<
l%3`n}*e^(gAOi!#Ee@MpaI&=ng=H}t0|NsK0|z?~69Bm3*a-jt

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/sphero.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/sphero.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c18e5dffcef2b5c7adb3e92614aaaa2715e23296
GIT binary patch
literal 647
zcmd1j<>g{vU|>-H5s>njk%8ech=Yuo7#J8F7#J9eMHm<uQW#Pga~Pr+Q<zeiTNt94
zQW%37G+ADP)cYlaRDxI_%+A2T0K(27o%0wN7-|@@7;2en7#1+5Fs3jqWMX8fVOYSF
z!n}|X%mSH+5M_agW--(<gH=KK1obl4Fi9}fveYnwY1R_v1uQizHLM~GCCpi@3)pH{
z7BWIvtP2@M7^E2%GS;%yumv+{viiMDVPIe=Vq{=ocnR`II>;9c3=ixz*>4FJ<QHd_
zWaj4;CzclHq!y><-C`-q&&j#PQl6Mua*HXi;1*kAQF3yA@h!HT%)G>$^jj=>`9-;!
z?6=s83o=rR@^7&egVb{smn0UI6qM#=m)v45N=>`P2^NS4F(GpCV0Fv|8JQ~?ii8*#
z7=9J%XXNLm>X#;!=9QG{7v&cl#g`ZBXXX``B<AGkLyV8l&CJV;PtMOP0XZwRNIxet
zNxz`7BqKl1SkKTvzc{lbRkt89IXf{uwHTKkh*5e4mAANxQq$tgGxM@jb3j2+EW^OS
zz{bSG#Kp+N$i>LU#Ki=nc^EmEI2hF!Ss05zNkfzQ7HeK<Zb4-cDBi(BU=JV>!VC-y
aw>WHa^HWN5Qtd!NUChG3z`()4!w3LvBc)vc

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/sphero_main.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/sphero_main.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d95a51ee66ceb429dcd3290ef44c9288bc375fdb
GIT binary patch
literal 3471
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
M7&#i4{;~W40PWr{761SM

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/test.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/test.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1652f1531f8f1fa2134712bba5ab5118856c0730
GIT binary patch
literal 767
zcmd1j<>g{vU|=}<y)@+=BLl-@5C<8vGcYhXFfcF_Z(?9zNMT4}%wdRv(2P+`sSFF4
zQ<xSqMzN%_EMQ&85W^J37R8>*uz(|#J(VGgb0Jd{S1Q8-?o_T+rUg7H%;}5^8Nn<T
z5NjcG6mJScI%6tV7GDahB!dWy%>ZIY@uxCn2`msy<z2`aC6p?h!jQ_F#h1b$$<WN?
z!Vt?FC6dCH!rsD=DwHZB$>74!%$UlbDq_P>=$a~;%HPb$$dJMq%%I8f6671dD#MJD
zk^(Dz{i6K*5-SklU}&IcXk?*hVyI_iY-wd-pr4ynkgi{rnUb2X2V%aAVqjo+`5#0u
zGB7YCg9wmWAk4(Tz`(-5z~BrD85sr!hIED+hFGpz#u~;HhHRE1t`x>R#uTQBOodFr
z44TX@PcSer++qy>#i+27L6hkglb*pX#;hU^1_lN&@he|HBR@A)zci^ducTDJD8JY!
zzPwmJGq1QLF(*gAxF937C_g?oGcPkfIX|zYC_g7BwMaiFGfBUovLquv&sfjUK)*P%
zBvrQ{F*!RiJ+&B@o|4q!61{@TTU<6dnZ+f^`MCvl!XQ6@JS4+V#KXYApec5XIl0W}
z7HeK<Zb9WOro4h%JYk?vaZW5KDJ@F9#hjd2aEqlVH8JHDdvR%Ua%yq$E#}PJ^jjRs
zWhKt}Ir&Am_?-QH{Db0y+?|ZvgB&Aov7{FzR^DRI%nM4)OHaMUnpgzlv*acgXWwEi
z&PXgsy~UNASm2))o?n!ca*I7L1)_qjBp>9?Tbv-3@n9xv5!eXE%v-DlMVWae-~dD-
uxIsb9VUwGmQks)$2a2>}F$M+(4kivpE@mDkJ|;Ov873Yk5he*n9wq>2#L{>G

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/treiber.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/treiber.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..371445741325a38df010cc651d7b73d397ff1efc
GIT binary patch
literal 18883
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
J^&lwb1pvP+0RR91

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefront.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefront.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..751df02c9c93c0c2ace4b207f86ae0998a1571c7
GIT binary patch
literal 3571
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
E03*Nm1poj5

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefront_coverage_path_planner.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefront_coverage_path_planner.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bb64c53ebc91edff78d10e432020a92c12d0dd20
GIT binary patch
literal 5730
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

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefrontgpt2.cpython-310.pyc b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/__pycache__/wavefrontgpt2.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..693e46d875943c27484df42e4d6294ef7faa6e5f
GIT binary patch
literal 1823
zcmd1j<>g{vU|{I7o{;jDi-F-Wh=Yt-85kHG7#J9egBTbXQW#Pga~N_NqZk<(QkYVh
zTNt94(iu`%7BQwXq_BcX1e+y_IfX5XC51hTHI*rqIh7@qwV64JEtNfmBbBY0iIE|N
zGnhe>>m|rGO~zZSfu*UXsmaVBE)?@IFff4Z2Z<FgVq#z@VW?qfW~^lf(J73Q49$$4
z3^j}(RtjS_L$MWvUBjHs3T87&GQh=|BpEswz~W3u>cMQNdZrYFdN3QLzR0eGF@?FA
zv5B#rA&oJGC55$xqlBr3xtY-g<Pw&2h7`6%jJ2#K%*_n7Y&C2PSZbISf<lL}hNT8<
zx+Fsl*fbl48ny+j3mJ;f*03#LTgXt$Uc>6b5F201QNs>$Q4I%(6lbVm2f3q$14N25
zq%qZUrZCoUg5+2jm>IGei`r|Lvl)s`<S{Wa6lQ|um?RmXa#K4P5OOsv5PgyiHJl*R
zBpFiJvzdxc)PVSmk_<@Vj9_sVh)X1)ZjfY1VG?IRHwEkumKsiwFAFmvekw|?VS$9b
zBq%<ZKxTvOx?94S!T}1s8pd?STCN(#TJ{?D8m4UK35-SlDGasTCG07j&5X4?;IQx}
z7#6%Kj5WN7u$aJD#19IM35-Qn;P7}4mWPMO1jZtHP>3MpYgi!qB^hdXAz@O(lg$8<
zui>rb#+0q)DSThUox)HGQsYv>n8F424c7vW8g5Vs)NsRmRQ$Y#E0{r(+pma`fq~&A
zh^W#CE=epZQOGY+NY78qQ7FhS&Me8y&r`@OR>&_cQOHkINXjqGODWb%1}TT8dIly2
z1_l-e1_ohJwi9DuU`S`EVTfg~WlUj6XY61QVVKBN$P~<=$@udB|NsA2GH5d0V$w6X
z#TdVm@fJ&Reok=_DAW9^(9g)vP1P?=D$Oe?)i25~Hi|DV*3Zl<E=kPE(JwB@NG-~b
z&&|xsj8D$bD=Es)$w@8J&&f>EFQ_cZ$j>v@Gc?dI&MZmQEl5nxPE1cN#-*n`u`D&M
zC_k?xy`aQMub}c4mrYJ)aY=H1Zh;*y$PXY7i7`~E!WG6B<Rs?hr55Sg<m4wO<`moM
zA#`Z6XfhRnyblgXO{OAH?uW5K!337nWC9C8BtfdH<RD><9LA-2MX8C&8Hq_bsd~4V
zGxO4_`26w}3KB~)6w*N9uBXX)i#aDX?-o~BVoqtQYf({t(Jj`Z#Ju#>B9NPJF&C7U
z++t15EhwqH#hjj6a*H)BCqJ>|7F%LLL26!#Cf_a2+{A+T#G<0a%3GYppvaCd$S=Od
z0g7%gi=`;Py!aL`!soe(1-H0TGK*4^K`Ej57Hc7>*t^A@Tv}9=npXnW#0i(b#h#a1
z4i;kpIr|nzUTOtI4Nq=nUVKVsaY<rca_TLfywuF}jHLV`kXmr`7jZB!Fcg8x_FIAo
z+o9nO3ew^<1_lNWMjl23W-dmi|HznwNsO6;nT?r?QG}U;k%N(gS%J}lS&WhCKL~3u
zaWOJAaD0{E<6vZCW?|%FWC5vRQebpo5@Tff&%z|a$kf2a#KFkL#KOq&fkmiDnSp^p
zlLZoE;3$L>Fj0_;Adv}@g2gVB4U&8bBC1#e5=%0y{4_a=q(R;TMH1NXB2f?*lvj$x
zK`eO&28LU#1x1;8C6Len<p>B193&hzx%nxjIjMFa8;U{tco;aC*zDODL6GGS3p)!V
I4-+3F0K)dPiU0rr

literal 0
HcmV?d00001

diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/_constants.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/_constants.py
new file mode 100644
index 0000000..fa8a0e8
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/_constants.py
@@ -0,0 +1,72 @@
+'''
+Known Peripheral UUIDs, obtained by querying using the Bluepy module:
+=====================================================================
+Anti DOS Characteristic <00020005-574f-4f20-5370-6865726f2121>
+Battery Level Characteristic <Battery Level>
+Peripheral Preferred Connection Parameters Characteristic <Peripheral Preferred Connection Parameters>
+API V2 Characteristic <00010002-574f-4f20-5370-6865726f2121>
+DFU Control Characteristic <00020002-574f-4f20-5370-6865726f2121>
+Name Characteristic <Device Name>
+Appearance Characteristic <Appearance>
+DFU Info Characteristic <00020004-574f-4f20-5370-6865726f2121>
+Service Changed Characteristic <Service Changed>
+Unknown1 Characteristic <00020003-574f-4f20-5370-6865726f2121>
+Unknown2 Characteristic <00010003-574f-4f20-5370-6865726f2121>
+
+The rest of the values saved in the dictionaries below, were borrowed from
+@igbopie's javacript library, which is available at https://github.com/igbopie/spherov2.js
+
+'''
+
+deviceID = {"apiProcessor": 0x10,                   # 16
+            "systemInfo": 0x11,                     # 17
+            "powerInfo": 0x13,                      # 19
+            "driving": 0x16,                        # 22
+            "animatronics": 0x17,                   # 23
+            "sensor": 0x18,                         # 24
+            "something": 0x19,                      # 25
+            "userIO": 0x1a,                         # 26
+            "somethingAPI": 0x1f}                   # 31
+
+SystemInfoCommands = {"mainApplicationVersion": 0x00,   # 00
+                      "bootloaderVersion": 0x01,    # 01
+                      "something": 0x06,            # 06
+                      "something2": 0x13,           # 19
+                      "something6": 0x12,           # 18    
+                      "something7": 0x28}           # 40
+
+sendPacketConstants = {"StartOfPacket": 0x8d,       # 141
+                       "EndOfPacket": 0xd8}         # 216
+
+userIOCommandIDs = {"allLEDs": 0x0e}                # 14
+
+flags= {"isResponse": 0x01,                         # 0x01
+        "requestsResponse": 0x02,                   # 0x02
+        "requestsOnlyErrorResponse": 0x04,          # 0x04
+        "resetsInactivityTimeout": 0x08}            # 0x08
+
+powerCommandIDs={"deepSleep": 0x00,                 # 0
+                "sleep": 0x01,                      # 01
+                "batteryVoltage": 0x03,             # 03
+                "wake": 0x0D,                       # 13
+                "something": 0x05,                  # 05 
+                "something2": 0x10,                 # 16         
+                "something3": 0x04,                 # 04
+                "something4": 0x1E}                 # 30
+
+drivingCommands={"rawMotor": 0x01,                  # 1
+                 "resetHeading": 0x06,              # 6    
+                 "driveAsSphero": 0x04,             # 4
+                 "driveAsRc": 0x02,                 # 2
+                 "driveWithHeading": 0x07,          # 7
+                 "stabilization": 0x0C}             # 12
+
+sensorCommands={'sensorMask': 0x00,                 # 00
+                'sensorResponse': 0x02,             # 02
+                'configureCollision': 0x11,         # 17
+                'collisionDetectedAsync': 0x12,     # 18
+                'resetLocator': 0x13,               # 19
+                'enableCollisionAsync': 0x14,       # 20
+                'sensor1': 0x0F,                    # 15
+                'sensor2': 0x17,                    # 23
+                'configureSensorStream': 0x0C}      # 12
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/a_star.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/a_star.py
new file mode 100644
index 0000000..6d20350
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/a_star.py
@@ -0,0 +1,282 @@
+"""
+
+A* grid planning
+
+author: Atsushi Sakai(@Atsushi_twi)
+        Nikos Kanargias (nkana@tee.gr)
+
+See Wikipedia article (https://en.wikipedia.org/wiki/A*_search_algorithm)
+
+"""
+
+import math
+
+import matplotlib.pyplot as plt
+
+show_animation = True
+
+
+class AStarPlanner:
+
+    def __init__(self, ox, oy, resolution, rr):
+        """
+        Initialize grid map for a star planning
+
+        ox: x position list of Obstacles [m]
+        oy: y position list of Obstacles [m]
+        resolution: grid resolution [m]
+        rr: robot radius[m]
+        """
+
+        self.resolution = resolution
+        self.rr = rr
+        self.min_x, self.min_y = 0, 0
+        self.max_x, self.max_y = 0, 0
+        self.obstacle_map = None
+        self.x_width, self.y_width = 0, 0
+        self.motion = self.get_motion_model()
+        self.calc_obstacle_map(ox, oy)
+
+    class Node:
+        def __init__(self, x, y, cost, parent_index):
+            self.x = x  # index of grid
+            self.y = y  # index of grid
+            self.cost = cost
+            self.parent_index = parent_index
+
+        def __str__(self):
+            return str(self.x) + "," + str(self.y) + "," + str(
+                self.cost) + "," + str(self.parent_index)
+
+    def planning(self, sx, sy, gx, gy):
+        """
+        A star path search
+
+        input:
+            s_x: start x position [m]
+            s_y: start y position [m]
+            gx: goal x position [m]
+            gy: goal y position [m]
+
+        output:
+            rx: x position list of the final path
+            ry: y position list of the final path
+        """
+
+        start_node = self.Node(self.calc_xy_index(sx, self.min_x),
+                               self.calc_xy_index(sy, self.min_y), 0.0, -1)
+        goal_node = self.Node(self.calc_xy_index(gx, self.min_x),
+                              self.calc_xy_index(gy, self.min_y), 0.0, -1)
+
+        open_set, closed_set = dict(), dict()
+        open_set[self.calc_grid_index(start_node)] = start_node
+
+        while True:
+            if len(open_set) == 0:
+                print("Open set is empty..")
+                break
+
+            c_id = min(
+                open_set,
+                key=lambda o: open_set[o].cost + self.calc_heuristic(goal_node,
+                                                                     open_set[
+                                                                         o]))
+            current = open_set[c_id]
+
+            # show graph
+            if show_animation:  # pragma: no cover
+                plt.plot(self.calc_grid_position(current.x, self.min_x),
+                         self.calc_grid_position(current.y, self.min_y), "xc")
+                # for stopping simulation with the esc key.
+                plt.gcf().canvas.mpl_connect('key_release_event',
+                                             lambda event: [exit(
+                                                 0) if event.key == 'escape' else None])
+                if len(closed_set.keys()) % 10 == 0:
+                    plt.pause(0.001)
+
+            if current.x == goal_node.x and current.y == goal_node.y:
+                print("Find goal")
+                goal_node.parent_index = current.parent_index
+                goal_node.cost = current.cost
+                break
+
+            # Remove the item from the open set
+            del open_set[c_id]
+
+            # Add it to the closed set
+            closed_set[c_id] = current
+
+            # expand_grid search grid based on motion model
+            for i, _ in enumerate(self.motion):
+                node = self.Node(current.x + self.motion[i][0],
+                                 current.y + self.motion[i][1],
+                                 current.cost + self.motion[i][2], c_id)
+                n_id = self.calc_grid_index(node)
+
+                # If the node is not safe, do nothing
+                if not self.verify_node(node):
+                    continue
+
+                if n_id in closed_set:
+                    continue
+
+                if n_id not in open_set:
+                    open_set[n_id] = node  # discovered a new node
+                else:
+                    if open_set[n_id].cost > node.cost:
+                        # This path is the best until now. record it
+                        open_set[n_id] = node
+
+        rx, ry = self.calc_final_path(goal_node, closed_set)
+
+        return rx, ry
+
+    def calc_final_path(self, goal_node, closed_set):
+        # generate final course
+        rx, ry = [self.calc_grid_position(goal_node.x, self.min_x)], [
+            self.calc_grid_position(goal_node.y, self.min_y)]
+        parent_index = goal_node.parent_index
+        while parent_index != -1:
+            n = closed_set[parent_index]
+            rx.append(self.calc_grid_position(n.x, self.min_x))
+            ry.append(self.calc_grid_position(n.y, self.min_y))
+            parent_index = n.parent_index
+
+        return rx, ry
+
+    @staticmethod
+    def calc_heuristic(n1, n2):
+        w = 1.0  # weight of heuristic
+        d = w * math.hypot(n1.x - n2.x, n1.y - n2.y)
+        return d
+
+    def calc_grid_position(self, index, min_position):
+        """
+        calc grid position
+
+        :param index:
+        :param min_position:
+        :return:
+        """
+        pos = index * self.resolution + min_position
+        return pos
+
+    def calc_xy_index(self, position, min_pos):
+        return round((position - min_pos) / self.resolution)
+
+    def calc_grid_index(self, node):
+        return (node.y - self.min_y) * self.x_width + (node.x - self.min_x)
+
+    def verify_node(self, node):
+        px = self.calc_grid_position(node.x, self.min_x)
+        py = self.calc_grid_position(node.y, self.min_y)
+
+        if px < self.min_x:
+            return False
+        elif py < self.min_y:
+            return False
+        elif px >= self.max_x:
+            return False
+        elif py >= self.max_y:
+            return False
+
+        # collision check
+        if self.obstacle_map[node.x][node.y]:
+            return False
+
+        return True
+
+    def calc_obstacle_map(self, ox, oy):
+
+        self.min_x = round(min(ox))
+        self.min_y = round(min(oy))
+        self.max_x = round(max(ox))
+        self.max_y = round(max(oy))
+        print("min_x:", self.min_x)
+        print("min_y:", self.min_y)
+        print("max_x:", self.max_x)
+        print("max_y:", self.max_y)
+
+        self.x_width = round((self.max_x - self.min_x) / self.resolution)
+        self.y_width = round((self.max_y - self.min_y) / self.resolution)
+        print("x_width:", self.x_width)
+        print("y_width:", self.y_width)
+
+        # obstacle map generation
+        self.obstacle_map = [[False for _ in range(self.y_width)]
+                             for _ in range(self.x_width)]
+        for ix in range(self.x_width):
+            x = self.calc_grid_position(ix, self.min_x)
+            for iy in range(self.y_width):
+                y = self.calc_grid_position(iy, self.min_y)
+                for iox, ioy in zip(ox, oy):
+                    d = math.hypot(iox - x, ioy - y)
+                    if d <= self.rr:
+                        self.obstacle_map[ix][iy] = True
+                        break
+
+    @staticmethod
+    def get_motion_model():
+        # dx, dy, cost
+        motion = [[1, 0, 1],
+                  [0, 1, 1],
+                  [-1, 0, 1],
+                  [0, -1, 1],
+                  [-1, -1, math.sqrt(2)],
+                  [-1, 1, math.sqrt(2)],
+                  [1, -1, math.sqrt(2)],
+                  [1, 1, math.sqrt(2)]]
+
+        return motion
+
+
+def main():
+    print(__file__ + " start!!")
+
+    # start and goal position
+    sx = 10.0  # [m]
+    sy = 10.0  # [m]
+    gx = 50.0  # [m]
+    gy = 50.0  # [m]
+    grid_size = 2.0  # [m]
+    robot_radius = 1.0  # [m]
+
+    # set obstacle positions
+    ox, oy = [], []
+    for i in range(-10, 60):
+        ox.append(i)
+        oy.append(-10.0)
+    for i in range(-10, 60):
+        ox.append(60.0)
+        oy.append(i)
+    for i in range(-10, 61):
+        ox.append(i)
+        oy.append(60.0)
+    for i in range(-10, 61):
+        ox.append(-10.0)
+        oy.append(i)
+    for i in range(-10, 40):
+        ox.append(20.0)
+        oy.append(i)
+    for i in range(0, 40):
+        ox.append(40.0)
+        oy.append(60.0 - i)
+
+    if show_animation:  # pragma: no cover
+        plt.plot(ox, oy, ".k")
+        plt.plot(sx, sy, "og")
+        plt.plot(gx, gy, "xb")
+        plt.grid(True)
+        plt.axis("equal")
+
+    a_star = AStarPlanner(ox, oy, grid_size, robot_radius)
+    rx, ry = a_star.planning(sx, sy, gx, gy)
+
+    if show_animation:  # pragma: no cover
+        plt.plot(rx, ry, "-r")
+        plt.pause(0.001)
+        plt.show()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/blobErkennung.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/blobErkennung.py
new file mode 100644
index 0000000..20036f5
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/blobErkennung.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+#cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+cap = cv2.VideoCapture(4)
+
+# Set up the detector with default parameters.
+detector = cv2.SimpleBlobDetector()
+ 
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+params.filterByArea = True
+params.minArea = 20
+params.maxArea = 200
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+params.filterByInertia = True
+params.minInertiaRatio = 0.5
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+
+success, img = cap.read()
+height, width = img.shape[:2]
+
+def calc_trans(x,y):
+    yTrans = height - y
+    xTrans = x
+
+    return xTrans, yTrans
+
+while True:
+
+    success, img = cap.read()
+    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+
+    # Detect blobs.
+    keypoints = detector.detect(gray)
+
+    #print(keypoints)
+    for keyPoint in keypoints:
+        x = keyPoint.pt[0]
+        y = keyPoint.pt[1]
+        #s = keyPoint.sizekeyPoints
+
+    # Draw detected blobs as red circles.
+    # cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
+    # the size of the circle corresponds to the size of blob
+
+    im_with_keypoints = cv2.drawKeypoints(gray, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
+
+    # Show blobs
+    cv2.imshow("Keypoints", im_with_keypoints)
+
+    if cv2.waitKey(10) & 0xFF == ord('q'):
+        break
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/core.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/core.py
new file mode 100644
index 0000000..e8fecdc
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/core.py
@@ -0,0 +1,638 @@
+from bluepy.btle import Peripheral
+from bluepy import btle
+from _constants import *
+import struct
+import time
+import sys
+
+class SpheroMini():
+    def __init__(self, MACAddr, verbosity = 4, user_delegate = None):
+        '''
+        initialize class instance and then build collect BLE sevices and characteristics.
+        Also sends text string to Anti-DOS characteristic to prevent returning to sleep,
+        and initializes notifications (which is what the sphero uses to send data back to
+        the client).
+        '''
+        self.verbosity = verbosity # 0 = Silent,
+                                   # 1 = Connection/disconnection only
+                                   # 2 = Init messages
+                                   # 3 = Recieved commands
+                                   # 4 = Acknowledgements
+        self.sequence = 1
+        self.v_batt = None # will be updated with battery voltage when sphero.getBatteryVoltage() is called
+        self.firmware_version = [] # will be updated with firware version when sphero.returnMainApplicationVersion() is called
+
+        if self.verbosity > 0:
+            print("[INFO] Connecting to %s", MACAddr)
+        self.p = Peripheral(MACAddr, "random") #connect
+
+        if self.verbosity > 1:
+            print("[INIT] Initializing")
+
+        # Subscribe to notifications
+        self.sphero_delegate = MyDelegate(self, user_delegate) # Pass a reference to this instance when initializing
+        self.p.setDelegate(self.sphero_delegate)
+
+        if self.verbosity > 1:
+            print("[INIT] Read all characteristics and descriptors")
+        # Get characteristics and descriptors
+        self.API_V2_characteristic = self.p.getCharacteristics(uuid="00010002-574f-4f20-5370-6865726f2121")[0]
+        self.AntiDOS_characteristic = self.p.getCharacteristics(uuid="00020005-574f-4f20-5370-6865726f2121")[0]
+        self.DFU_characteristic = self.p.getCharacteristics(uuid="00020002-574f-4f20-5370-6865726f2121")[0]
+        self.DFU2_characteristic = self.p.getCharacteristics(uuid="00020004-574f-4f20-5370-6865726f2121")[0]
+        self.API_descriptor = self.API_V2_characteristic.getDescriptors(forUUID=0x2902)[0]
+        self.DFU_descriptor = self.DFU_characteristic.getDescriptors(forUUID=0x2902)[0]
+
+        # The rest of this sequence was observed during bluetooth sniffing:
+        # Unlock code: prevent the sphero mini from going to sleep again after 10 seconds
+        if self.verbosity > 1:
+            print("[INIT] Writing AntiDOS characteristic unlock code")
+        self.AntiDOS_characteristic.write("usetheforce...band".encode(), withResponse=True)
+
+        # Enable DFU notifications:
+        if self.verbosity > 1:
+            print("[INIT] Configuring DFU descriptor")
+        self.DFU_descriptor.write(struct.pack('<bb', 0x01, 0x00), withResponse = True)
+
+        # No idea what this is for. Possibly a device ID of sorts? Read request returns '00 00 09 00 0c 00 02 02':
+        if self.verbosity > 1:
+            print("[INIT] Reading DFU2 characteristic")
+        _ = self.DFU2_characteristic.read()
+
+        # Enable API notifications:
+        if self.verbosity > 1:
+            print("[INIT] Configuring API dectriptor")
+        self.API_descriptor.write(struct.pack('<bb', 0x01, 0x00), withResponse = True)
+
+        self.wake()
+
+        # Finished initializing:
+        if self.verbosity > 1:
+            print("[INIT] Initialization complete\n")
+
+    def disconnect(self):
+        if self.verbosity > 0:
+            print("[INFO] Disconnecting")
+        
+        self.p.disconnect()
+
+    def wake(self):
+        '''
+        Bring device out of sleep mode (can only be done if device was in sleep, not deep sleep).
+        If in deep sleep, the device should be connected to USB power to wake.
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Waking".format(self.sequence))
+        
+        self._send(characteristic=self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=powerCommandIDs["wake"],
+                   payload=[]) # empty payload
+
+        self.getAcknowledgement("Wake")
+
+    def sleep(self, deepSleep=False):
+        '''
+        Put device to sleep or deep sleep (deep sleep needs USB power connected to wake up)
+        '''
+        if deepSleep:
+            sleepCommID=powerCommandIDs["deepSleep"]
+            if self.verbosity > 0:
+                print("[INFO] Going into deep sleep. Connect USB power to wake.")
+        else:
+            sleepCommID=powerCommandIDs["sleep"]
+        self._send(characteristic=self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=sleepCommID,
+                   payload=[]) #empty payload
+
+    def setLEDColor(self, red = None, green = None, blue = None):
+        '''
+        Set device LED color based on RGB vales (each can  range between 0 and 0xFF)
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Setting main LED colour to [{}, {}, {}]".format(self.sequence, red, green, blue))
+        
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['userIO'], # 0x1a
+                  commID = userIOCommandIDs["allLEDs"], # 0x0e
+                  payload = [0x00, 0x0e, red, green, blue])
+
+        self.getAcknowledgement("LED/backlight")
+
+    def setBackLEDIntensity(self, brightness=None):
+        '''
+        Set device LED backlight intensity based on 0-255 values
+
+        NOTE: this is not the same as aiming - it only turns on the LED
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Setting backlight intensity to {}".format(self.sequence, brightness))
+
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['userIO'],
+                  commID = userIOCommandIDs["allLEDs"],
+                  payload = [0x00, 0x01, brightness])
+
+        self.getAcknowledgement("LED/backlight")
+
+    def roll(self, speed=None, heading=None):
+        '''
+        Start to move the Sphero at a given direction and speed.
+        heading: integer from 0 - 360 (degrees)
+        speed: Integer from 0 - 255
+
+        Note: the zero heading should be set at startup with the resetHeading method. Otherwise, it may
+        seem that the sphero doesn't honor the heading argument
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Rolling with speed {} and heading {}".format(self.sequence, speed, heading))
+    
+        if abs(speed) > 255:
+            print("WARNING: roll speed parameter outside of allowed range (-255 to +255)")
+
+        if speed < 0:
+            speed = -1*speed+256 # speed values > 256 in the send packet make the spero go in reverse
+
+        speedH = (speed & 0xFF00) >> 8
+        speedL = speed & 0xFF
+        headingH = (heading & 0xFF00) >> 8
+        headingL = heading & 0xFF
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['driving'],
+                  commID = drivingCommands["driveWithHeading"],
+                  payload = [speedL, headingH, headingL, speedH])
+
+        self.getAcknowledgement("Roll")
+
+    def resetHeading(self):
+        '''
+        Reset the heading zero angle to the current heading (useful during aiming)
+        Note: in order to manually rotate the sphero, you need to call stabilization(False).
+        Once the heading has been set, call stabilization(True).
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Resetting heading".format(self.sequence))
+    
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['driving'],
+                  commID = drivingCommands["resetHeading"],
+                  payload = []) #empty payload
+
+        self.getAcknowledgement("Heading")
+
+    def returnMainApplicationVersion(self):
+        '''
+        Sends command to return application data in a notification
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Requesting firmware version".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID = deviceID['systemInfo'],
+                   commID = SystemInfoCommands['mainApplicationVersion'],
+                   payload = []) # empty
+
+        self.getAcknowledgement("Firmware")
+
+    def getBatteryVoltage(self):
+        '''
+        Sends command to return battery voltage data in a notification.
+        Data printed to console screen by the handleNotifications() method in the MyDelegate class.
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Requesting battery voltage".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=powerCommandIDs['batteryVoltage'],
+                   payload=[]) # empty
+
+        self.getAcknowledgement("Battery")
+
+    def stabilization(self, stab = True):
+        '''
+        Sends command to turn on/off the motor stabilization system (required when manually turning/aiming the sphero)
+        '''
+        if stab == True:
+            if self.verbosity > 2:
+                    print("[SEND {}] Enabling stabilization".format(self.sequence))
+            val = 1
+        else:
+            if self.verbosity > 2:
+                    print("[SEND {}] Disabling stabilization".format(self.sequence))
+            val = 0
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['driving'],
+                   commID=drivingCommands['stabilization'],
+                   payload=[val])
+
+        self.getAcknowledgement("Stabilization")
+
+    def wait(self, delay):
+        '''
+        This is a non-blocking delay command. It is similar to time.sleep(), except it allows asynchronous 
+        notification handling to still be performed.
+        '''
+        start = time.time()
+        while(1):
+            self.p.waitForNotifications(0.001)
+            if time.time() - start > delay:
+                break
+
+    def _send(self, characteristic=None, devID=None, commID=None, payload=[]):
+        '''
+        A generic "send" method, which will be used by other methods to send a command ID, payload and
+        appropriate checksum to a specified device ID. Mainly useful because payloads are optional,
+        and can be of varying length, to convert packets to binary, and calculate and send the
+        checksum. For internal use only.
+
+        Packet structure has the following format (in order):
+
+        - Start byte: always 0x8D
+        - Flags byte: indicate response required, etc
+        - Virtual device ID: see _constants.py
+        - Command ID: see _constants.py
+        - Sequence number: Seems to be arbitrary. I suspect it is used to match commands to response packets (in which the number is echoed).
+        - Payload: Could be varying number of bytes (incl. none), depending on the command
+        - Checksum: See below for calculation
+        - End byte: always 0xD8
+
+        '''
+        sendBytes = [sendPacketConstants["StartOfPacket"],
+                    sum([flags["resetsInactivityTimeout"], flags["requestsResponse"]]),
+                    devID,
+                    commID,
+                    self.sequence] + payload # concatenate payload list
+
+        self.sequence += 1 # Increment sequence number, ensures we can identify response packets are for this command
+        if self.sequence > 255:
+            self.sequence = 0
+
+        # Compute and append checksum and add EOP byte:
+        # From Sphero docs: "The [checksum is the] modulo 256 sum of all the bytes
+        #                   from the device ID through the end of the data payload,
+        #                   bit inverted (1's complement)"
+        # For the sphero mini, the flag bits must be included too:
+        checksum = 0
+        for num in sendBytes[1:]:
+            checksum = (checksum + num) & 0xFF # bitwise "and to get modulo 256 sum of appropriate bytes
+        checksum = 0xff - checksum # bitwise 'not' to invert checksum bits
+        sendBytes += [checksum, sendPacketConstants["EndOfPacket"]] # concatenate
+
+        # Convert numbers to bytes
+        output = b"".join([x.to_bytes(1, byteorder='big') for x in sendBytes])
+
+        #send to specified characteristic:
+        characteristic.write(output, withResponse = True)
+
+    def getAcknowledgement(self, ack):
+        #wait up to 10 secs for correct acknowledgement to come in, including sequence number!
+        start = time.time()
+        while(1):
+            self.p.waitForNotifications(1)
+            if self.sphero_delegate.notification_seq == self.sequence-1: # use one less than sequence, because _send function increments it for next send. 
+                if self.verbosity > 3:
+                    print("[RESP {}] {}".format(self.sequence-1, self.sphero_delegate.notification_ack))
+                self.sphero_delegate.clear_notification()
+                break
+            elif self.sphero_delegate.notification_seq >= 0:
+                print("Unexpected ACK. Expected: {}/{}, received: {}/{}".format(
+                    ack, self.sequence, self.sphero_delegate.notification_ack.split()[0],
+                    self.sphero_delegate.notification_seq)
+                    )
+            if time.time() > start + 10:
+                print("Timeout waiting for acknowledgement: {}/{}".format(ack, self.sequence))
+                break
+
+# =======================================================================
+# The following functions are experimental:
+# =======================================================================
+
+    def configureCollisionDetection(self,
+                                     xThreshold = 50, 
+                                     yThreshold = 50, 
+                                     xSpeed = 50, 
+                                     ySpeed = 50, 
+                                     deadTime = 50, # in 10 millisecond increments
+                                     method = 0x01, # Must be 0x01        
+                                     callback = None):
+        '''
+        Appears to function the same as other Sphero models, however speed settings seem to have no effect. 
+        NOTE: Setting to zero seems to cause bluetooth errors with the Sphero Mini/bluepy library - set to 
+        255 to make it effectively disabled.
+
+        deadTime disables future collisions for a short period of time to avoid repeat triggering by the same
+        event. Set in 10ms increments. So if deadTime = 50, that means the delay will be 500ms, or half a second.
+        
+        From Sphero docs:
+        
+            xThreshold/yThreshold: An 8-bit settable threshold for the X (left/right) and Y (front/back) axes 
+            of Sphero.
+
+            xSpeed/ySpeed: An 8-bit settable speed value for the X and Y axes. This setting is ranged by the 
+            speed, then added to xThreshold, yThreshold to generate the final threshold value.
+        '''
+        
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring collision detection".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['configureCollision'],
+                   payload=[method, xThreshold, xSpeed, yThreshold, ySpeed, deadTime])
+
+        self.collision_detection_callback = callback
+
+        self.getAcknowledgement("Collision")
+
+    def configureSensorStream(self): # Use default values
+        '''
+        Send command to configure sensor stream using default values as found during bluetooth 
+        sniffing of the Sphero Edu app.
+
+        Must be called after calling configureSensorMask()
+        '''
+        bitfield1 = 0b00000000 # Unknown function - needs experimenting
+        bitfield2 = 0b00000000 # Unknown function - needs experimenting
+        bitfield3 = 0b00000000 # Unknown function - needs experimenting
+        bitfield4 = 0b00000000 # Unknown function - needs experimenting
+
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring sensor stream".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['configureSensorStream'],
+                   payload=[bitfield1, bitfield1, bitfield1, bitfield1])
+
+        self.getAcknowledgement("Sensor")
+
+    def configureSensorMask(self,
+                            sample_rate_divisor = 0x25, # Must be > 0
+                            packet_count = 0,
+                            IMU_pitch = False,
+                            IMU_roll = False,
+                            IMU_yaw = False,
+                            IMU_acc_x = False,
+                            IMU_acc_y = False,
+                            IMU_acc_z = False,
+                            IMU_gyro_x = False,
+                            IMU_gyro_y = False,
+                            IMU_gyro_z = False):
+
+        '''
+        Send command to configure sensor mask using default values as found during bluetooth 
+        sniffing of the Sphero Edu app. From experimentation, it seems that these are he functions of each:
+        
+        Sampling_rate_divisor. Slow data EG: Set to 0x32 to the divide data rate by 50. Setting below 25 (0x19) causes 
+                bluetooth errors        
+        
+        Packet_count: Select the number of packets to transmit before ending the stream. Set to zero to stream infinitely
+        
+        All IMU bool parameters: Toggle transmission of that value on or off (e.g. set IMU_acc_x = True to include the 
+                X-axis accelerometer readings in the sensor stream)
+        '''
+
+        # Construct bitfields based on function parameters:
+        IMU_bitfield1 = (IMU_pitch<<2) + (IMU_roll<<1) + IMU_yaw
+        IMU_bitfield2 = ((IMU_acc_y<<7) + (IMU_acc_z<<6) + (IMU_acc_x<<5) + \
+                         (IMU_gyro_y<<4) + (IMU_gyro_x<<2) + (IMU_gyro_z<<2))
+        
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring sensor mask".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensorMask'],
+                   payload=[0x00,               # Unknown param - altering it seems to slow data rate. Possibly averages multiple readings?
+                            sample_rate_divisor,       
+                            packet_count,       # Packet count: select the number of packets to stop streaming after (zero = infinite)
+                            0b00,               # Unknown param: seems to be another accelerometer bitfield? Z-acc, Y-acc
+                            IMU_bitfield1,
+                            IMU_bitfield2,
+                            0b00])              # reserved, Position?, Position?, velocity?, velocity?, Y-gyro, timer, reserved
+
+        self.getAcknowledgement("Mask")
+
+        '''
+        Since the sensor values arrive as unlabelled lists in the order that they appear in the bitfields above, we need 
+        to create a list of sensors that have been configured.Once we have this list, then in the default_delegate class, 
+        we can get sensor values as attributes of the sphero_mini class.
+        e.g. print(sphero.IMU_yaw) # displays the current yaw angle
+        '''
+
+        # Initialize dictionary with sensor names as keys and their bool values (set by the user) as values:
+        availableSensors = {"IMU_pitch" : IMU_pitch,
+                            "IMU_roll" : IMU_roll,
+                            "IMU_yaw" : IMU_yaw,
+                            "IMU_acc_y" : IMU_acc_y,
+                            "IMU_acc_z" : IMU_acc_z,
+                            "IMU_acc_x" : IMU_acc_x,
+                            "IMU_gyro_y" : IMU_gyro_y,
+                            "IMU_gyro_x" : IMU_gyro_x,
+                            "IMU_gyro_z" : IMU_gyro_z}
+        
+        # Create list of of only sensors that have been "activated" (set as true in the method arguments):
+        self.configured_sensors = [name for name in availableSensors if availableSensors[name] == True]
+
+    def sensor1(self): # Use default values
+        '''
+        Unknown function. Observed in bluetooth sniffing. 
+        '''
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensor1'],
+                   payload=[0x01])
+
+        self.getAcknowledgement("Sensor1")
+
+    def sensor2(self): # Use default values
+        '''
+        Unknown function. Observed in bluetooth sniffing. 
+        '''
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensor2'],
+                   payload=[0x00])
+
+        self.getAcknowledgement("Sensor2")
+
+# =======================================================================
+
+class MyDelegate(btle.DefaultDelegate):
+
+    '''
+    This class handles notifications (both responses and asynchronous notifications).
+    
+    Usage of this class is described in the Bluepy documentation
+    
+    '''
+
+    def __init__(self, sphero_class, user_delegate):
+        self.sphero_class = sphero_class # for saving sensor values as attributes of sphero class instance
+        self.user_delegate = user_delegate # to directly notify users of callbacks
+        btle.DefaultDelegate.__init__(self)
+        self.clear_notification()
+        self.notificationPacket = []
+
+    def clear_notification(self):
+        self.notification_ack = "DEFAULT ACK"
+        self.notification_seq = -1
+
+    def bits_to_num(self, bits):
+        '''
+        This helper function decodes bytes from sensor packets into single precision floats. Encoding follows the
+        the IEEE-754 standard.
+        '''
+        num = int(bits, 2).to_bytes(len(bits) // 8, byteorder='little')
+        num = struct.unpack('f', num)[0]
+        return num
+
+    def handleNotification(self, cHandle, data):
+        '''
+        This method acts as an interrupt service routine. When a notification comes in, this
+        method is invoked, with the variable 'cHandle' being the handle of the characteristic that
+        sent the notification, and 'data' being the payload (sent one byte at a time, so the packet
+        needs to be reconstructed)  
+
+        The method keeps appending bytes to the payload packet byte list until end-of-packet byte is
+        encountered. Note that this is an issue, because 0xD8 could be sent as part of the payload of,
+        say, the battery voltage notification. In future, a more sophisticated method will be required.
+        '''
+        # Allow the user to intercept and process data first..
+        if self.user_delegate != None:
+            if self.user_delegate.handleNotification(cHandle, data):
+                return
+        
+        print("Received notification with packet %s", str(data))
+
+        for data_byte in data: # parse each byte separately (sometimes they arrive simultaneously)
+
+            self.notificationPacket.append(data_byte) # Add new byte to packet list
+
+            # If end of packet (need to find a better way to segment the packets):
+            if data_byte == sendPacketConstants['EndOfPacket']:
+                # Once full the packet has arrived, parse it:
+                # Packet structure is similar to the outgoing send packets (see docstring in sphero_mini._send())
+                
+                # Attempt to unpack. Might fail if packet is too badly corrupted
+                try:
+                    start, flags_bits, devid, commcode, seq, *notification_payload, chsum, end = self.notificationPacket
+                except ValueError:
+                    print("Warning: notification packet unparseable %s", self.notificationPacket)
+                    self.notificationPacket = [] # Discard this packet
+                    return # exit
+
+                # Compute and append checksum and add EOP byte:
+                # From Sphero docs: "The [checksum is the] modulo 256 sum of all the bytes
+                #                   from the device ID through the end of the data payload,
+                #                   bit inverted (1's complement)"
+                # For the sphero mini, the flag bits must be included too:
+                checksum_bytes = [flags_bits, devid, commcode, seq] + notification_payload
+                checksum = 0 # init
+                for num in checksum_bytes:
+                    checksum = (checksum + num) & 0xFF # bitwise "and to get modulo 256 sum of appropriate bytes
+                checksum = 0xff - checksum # bitwise 'not' to invert checksum bits
+                if checksum != chsum: # check computed checksum against that recieved in the packet
+                    print("Warning: notification packet checksum failed - %s", str(self.notificationPacket))
+                    self.notificationPacket = [] # Discard this packet
+                    return # exit
+
+                # Check if response packet:
+                if flags_bits & flags['isResponse']: # it is a response
+
+                    # Use device ID and command code to determine which command is being acknowledged:
+                    if devid == deviceID['powerInfo'] and commcode == powerCommandIDs['wake']:
+                        self.notification_ack = "Wake acknowledged" # Acknowledgement after wake command
+                        
+                    elif devid == deviceID['driving'] and commcode == drivingCommands['driveWithHeading']:
+                        self.notification_ack = "Roll command acknowledged"
+
+                    elif devid == deviceID['driving'] and commcode == drivingCommands['stabilization']:
+                        self.notification_ack = "Stabilization command acknowledged"
+
+                    elif devid == deviceID['userIO'] and commcode == userIOCommandIDs['allLEDs']:
+                        self.notification_ack = "LED/backlight color command acknowledged"
+
+                    elif devid == deviceID['driving'] and commcode == drivingCommands["resetHeading"]:
+                        self.notification_ack = "Heading reset command acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["configureCollision"]:
+                        self.notification_ack = "Collision detection configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["configureSensorStream"]:
+                        self.notification_ack = "Sensor stream configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensorMask"]:
+                        self.notification_ack = "Mask configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensor1"]:
+                        self.notification_ack = "Sensor1 acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensor2"]:
+                        self.notification_ack = "Sensor2 acknowledged"
+
+                    elif devid == deviceID['powerInfo'] and commcode == powerCommandIDs['batteryVoltage']:
+                        V_batt = notification_payload[2] + notification_payload[1]*256 + notification_payload[0]*65536
+                        V_batt /= 100 # Notification gives V_batt in 10mV increments. Divide by 100 to get to volts.
+                        self.notification_ack = "Battery voltage:" + str(V_batt) + "v"
+                        self.sphero_class.v_batt = V_batt
+
+                    elif devid == deviceID['systemInfo'] and commcode == SystemInfoCommands['mainApplicationVersion']:
+                        version = '.'.join(str(x) for x in notification_payload)
+                        self.notification_ack = "Firmware version: " + version
+                        self.sphero_class.firmware_version = notification_payload
+                                                
+                    else:
+                        self.notification_ack = "Unknown acknowledgement" #print(self.notificationPacket)
+                        print(self.notificationPacket, "===================> Unknown ack packet")
+
+                    self.notification_seq = seq
+
+                else: # Not a response packet - therefore, asynchronous notification (e.g. collision detection, etc):
+                    
+                    # Collision detection:
+                    if devid == deviceID['sensor'] and commcode == sensorCommands['collisionDetectedAsync']:
+                        # The first four bytes are data that is still un-parsed. the remaining unsaved bytes are always zeros
+                        _, _, _, _, _, _, axis, _, Y_mag, _, X_mag, *_ = notification_payload
+                        if axis == 1: 
+                            dir = "Left/right"
+                        else:
+                            dir = 'Forward/back'
+                        print("Collision detected:")
+                        print("\tAxis: %s", dir)
+                        print("\tX_mag: %s", X_mag)
+                        print("\tY_mag: %s", Y_mag)
+
+                        if self.sphero_class.collision_detection_callback is not None:
+                            self.notificationPacket = [] # need to clear packet, in case new notification comes in during callback
+                            self.sphero_class.collision_detection_callback()
+
+                    # Sensor response:
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands['sensorResponse']:
+                        # Convert to binary, pad bytes with leading zeros:
+                        val = ''
+                        for byte in notification_payload:
+                            val += format(int(bin(byte)[2:], 2), '#010b')[2:]
+                        
+                        # Break into 32-bit chunks
+                        nums = []
+                        while(len(val) > 0):
+                            num, val = val[:32], val[32:] # Slice off first 16 bits
+                            nums.append(num)
+                        
+                        # convert from raw bits to float:
+                        nums = [self.bits_to_num(num) for num in nums]
+
+                        # Set sensor values as class attributes:
+                        for name, value in zip(self.sphero_class.configured_sensors, nums):
+                            print("Setting sensor %s at %s.", name, str(value))
+                            setattr(self.sphero_class, name, value)
+                        
+                    # Unrecognized packet structure:
+                    else:
+                        self.notification_ack = "Unknown asynchronous notification" #print(self.notificationPacket)
+                        print(str(self.notificationPacket) + " ===================> Unknown async packet")
+                        
+                self.notificationPacket = [] # Start new payload after this byte
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/dynamicPathPlanning.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/dynamicPathPlanning.py
new file mode 100644
index 0000000..6607c85
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/dynamicPathPlanning.py
@@ -0,0 +1,504 @@
+import numpy as np
+import matplotlib.pyplot as plt
+import robotController as rc
+import mapGeneration as mg
+import random
+from controller import Robot
+
+#======[Scenario Control functions]============================================
+
+#This function causes the robot to wait some time steps before starting it's operation
+#DO NOT CHANGE THIS FUNCTION OR IT'S CALL IN THE CODE
+def waitRandomTimeSteps(turtle, stop=50):
+    initialPose = np.zeros(7)
+    initialPose[0:2] = findRobotPosition(turtle)
+    turtle.setPoseGoal(initialPose)
+    turtle.drive_goalPose()
+    nRand = random.randint(1, stop)
+    for i in range(nRand):
+        turtle.robot.step(turtle.TIME_STEP)
+    turtle.update()
+
+#=========[Example functions for finding objects in the map]===================
+
+def findTargetPosition(turtlebot):
+    mapInd = turtlebot.findInMap_FinalTarget()
+    if(len(mapInd) != 0):
+        pos = turtlebot.getPositionFromMapIndex(mapInd[0])
+    else:
+        pos = []
+    return np.array(pos, dtype=float).tolist()
+
+def findRobotPosition(turtlebot):
+    mapInds = turtlebot.findInMap_Robot()
+    robotPos = np.zeros((len(mapInds), 2))
+    for i in range(len(mapInds)):
+        pos = turtlebot.getPositionFromMapIndex(mapInds[i])
+        robotPos[i, ...] = pos
+    XYInd = np.average(robotPos, axis=0)
+    return np.array(XYInd, dtype=float).tolist()
+
+def findObstaclePositions(turtlebot):
+    mapInds = turtlebot.findInMap_Obstacles()
+    obsPos = np.zeros((len(mapInds), 2))
+    for i in range(len(mapInds)):
+        pos = turtlebot.getPositionFromMapIndex(mapInds[i])
+        obsPos[i, ...] = pos
+    return np.array(obsPos, dtype=float).tolist()
+
+#=========[Framework for own implementations of path tracking and planning]====
+
+def checkForPossibleCollisions(turtlebot, turtlePos, collisionCntr):
+    #Fill this with your collision detection between the planed path and 
+    #moving obstacles
+    hitBox = 0
+
+    faktor = 0.1
+
+    turtlePos1 = [turtlePos[0] + faktor, turtlePos[1] + faktor]
+    turtlePos2 = [turtlePos[0] + faktor, turtlePos[1] - faktor]
+    turtlePos3 = [turtlePos[0] - faktor, turtlePos[1] + faktor]
+    turtlePos4 = [turtlePos[0] - faktor, turtlePos[1] - faktor]
+
+    turtlePos5 = [turtlePos[0] + faktor, turtlePos[1]    ]
+    turtlePos6 = [turtlePos[0]    , turtlePos[1] + faktor]
+    turtlePos7 = [turtlePos[0] - faktor, turtlePos[1]    ]
+    turtlePos8 = [turtlePos[0]    , turtlePos[1] - faktor]
+
+    turtlePosBool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos))
+    turtlePos1Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos1))
+    turtlePos2Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos2))
+    turtlePos3Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos3))
+    turtlePos4Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos4))
+    turtlePos5Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos5))
+    turtlePos6Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos6))
+    turtlePos7Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos7))
+    turtlePos8Bool = bool(turtlebot.isMapAtPosition_Obstacle(turtlePos8))
+
+    hitBox = turtlePosBool | turtlePos1Bool | turtlePos2Bool | turtlePos3Bool | turtlePos4Bool | turtlePos5Bool | turtlePos6Bool | turtlePos7Bool | turtlePos8Bool
+
+    if(hitBox):
+        collisionCntr += 1
+        return True
+
+    if(~hitBox):
+        return False
+
+def staticPathTracking(turtlebot, path, indCntr):
+    #This delta value determines the precision of the position control during path tracking
+    #A high value leads towards a larger curve radius at corners in the path,
+    #  which might result in a smoothing of the path and keeping the velocity high.
+    #A lower value sets a higher precision for the precision control and thus, 
+    #  the robot might slow down when reaching a path point, but it stays very 
+    #  close to the original path
+    delta = 0.05
+    if(indCntr == (len(path)-1)):
+        delta = 0.01
+    #Control the turtlebot to drive towards the target position
+    isNearGoal = turtlebot.drive_goalPose(delta=delta)
+    #If the robot is close to the goal select the next goal position
+    if (isNearGoal):
+        indCntr += 1
+        i = min(indCntr, len(path))
+        if i == len(path):
+            indCntr = -1
+        else:
+            #print("Aktuelle Position Pfad: ", path[i])
+            turtlebot.setPoseGoal(path[i])
+    return indCntr
+
+def planInitialPath(turtle):
+
+    initialObstacles = findObstaclePositions(turtle)
+    initialPose = findRobotPosition(turtle)
+    initialFinalTarget = findTargetPosition(turtle)
+
+    plt.scatter(np.array(initialObstacles)[..., 0], np.array(initialObstacles)[..., 1])
+    plt.scatter(np.array(initialPose)[..., 0], np.array(initialPose)[..., 1] )
+    plt.scatter(np.array(initialFinalTarget)[..., 0], np.array(initialFinalTarget)[..., 1])
+    plt.show()
+    plt.pause(0.001)
+
+    from matplotlib import pyplot as ppl
+    from matplotlib import cm
+    import random, sys, math, os.path
+    from matplotlib.pyplot import imread
+
+    #Implementation of RRT
+
+    MAP_IMG = './karte.png'  #Black and white image for a map
+    MIN_NUM_VERT = 20  # Minimum number of vertex in the graph
+    MAX_NUM_VERT = 1500  # Maximum number of vertex in the graph
+    STEP_DISTANCE = 20  # Maximum distance between two vertex
+    SEED = None  # For random numbers
+
+    def rapidlyExploringRandomTree(ax, img, start, goal, seed=None):
+        hundreds = 100
+        seed = random.seed(seed)
+        #print("Zufallsseed: ", seed)
+        points = []
+        graph = []
+        points.append(start)
+        graph.append((start, []))
+        print('Generating and conecting random points')
+        occupied = True
+        phaseTwo = False
+
+        # Phase two values (points 5 step distances around the goal point)
+        minX = max(goal[0] - 5 * STEP_DISTANCE, 0)
+        maxX = min(goal[0] + 5 * STEP_DISTANCE, len(img[0]) - 1)
+        minY = max(goal[1] - 5 * STEP_DISTANCE, 0)
+        maxY = min(goal[1] + 5 * STEP_DISTANCE, len(img) - 1)
+
+        i = 0
+        while (goal not in points) and (len(points) < MAX_NUM_VERT):
+            if (i % 100) == 0:
+                print(i, 'points randomly generated')
+
+            if (len(points) % hundreds) == 0:
+                print(len(points), 'vertex generated')
+                hundreds = hundreds + 100
+
+            while (occupied):
+                if phaseTwo and (random.random() > 0.8):
+                    point = [random.randint(minX, maxX), random.randint(minY, maxY)]
+                else:
+                    point = [random.randint(0, len(img[0]) - 1), random.randint(0, len(img) - 1)]
+
+                if (img[point[1]][point[0]][0] * 255 == 255):
+                    occupied = False
+
+            occupied = True
+
+            nearest = findNearestPoint(points, point)
+            newPoints = connectPoints(point, nearest, img)
+            addToGraph(ax, graph, newPoints, point)
+            newPoints.pop(0)  # The first element is already in the points list
+            points.extend(newPoints)
+            ppl.draw()
+            i = i + 1
+
+            if len(points) >= MIN_NUM_VERT:
+                if not phaseTwo:
+                    print('Phase Two')
+                phaseTwo = True
+
+            if phaseTwo:
+                nearest = findNearestPoint(points, goal)
+                newPoints = connectPoints(goal, nearest, img)
+                addToGraph(ax, graph, newPoints, goal)
+                newPoints.pop(0)
+                points.extend(newPoints)
+                ppl.draw()
+
+        if goal in points:
+            print('Goal found, total vertex in graph:', len(points), 'total random points generated:', i)
+
+            path = searchPath(graph, start, [start])
+
+            for i in range(len(path) - 1):
+                ax.plot([path[i][0], path[i + 1][0]], [path[i][1], path[i + 1][1]], color='g', linestyle='-',
+                        linewidth=2)
+                ppl.draw()
+
+            print('Showing resulting map')
+            print('Final path:', path)
+            print('The final path is made from:', len(path), 'connected points')
+        else:
+            path = None
+            print('Reached maximum number of vertex and goal was not found')
+            print('Total vertex in graph:', len(points), 'total random points generated:', i)
+            print('Showing resulting map')
+
+        ppl.show()
+        return path
+
+    def searchPath(graph, point, path):
+        for i in graph:
+            if point == i[0]:
+                p = i
+
+        if p[0] == graph[-1][0]:
+            return path
+
+        for link in p[1]:
+            path.append(link)
+            finalPath = searchPath(graph, link, path)
+
+            if finalPath != None:
+                return finalPath
+            else:
+                path.pop()
+
+    def addToGraph(ax, graph, newPoints, point):
+        if len(newPoints) > 1:  # If there is anything to add to the graph
+            for p in range(len(newPoints) - 1):
+                nearest = [nearest for nearest in graph if (nearest[0] == [newPoints[p][0], newPoints[p][1]])]
+                nearest[0][1].append(newPoints[p + 1])
+                graph.append((newPoints[p + 1], []))
+
+                if not p == 0:
+                    ax.plot(newPoints[p][0], newPoints[p][1], '+k')  # First point is already painted
+                ax.plot([newPoints[p][0], newPoints[p + 1][0]], [newPoints[p][1], newPoints[p + 1][1]], color='k',
+                        linestyle='-', linewidth=1)
+
+            if point in newPoints:
+                ax.plot(point[0], point[1], '.g')  # Last point is green
+            else:
+                ax.plot(newPoints[p + 1][0], newPoints[p + 1][1], '+k')  # Last point is not green
+
+    def connectPoints(a, b, img):
+        newPoints = []
+        newPoints.append([b[0], b[1]])
+        step = [(a[0] - b[0]) / float(STEP_DISTANCE), (a[1] - b[1]) / float(STEP_DISTANCE)]
+
+        # Set small steps to check for walls
+        pointsNeeded = int(math.floor(max(math.fabs(step[0]), math.fabs(step[1]))))
+
+        if math.fabs(step[0]) > math.fabs(step[1]):
+            if step[0] >= 0:
+                step = [1, step[1] / math.fabs(step[0])]
+            else:
+                step = [-1, step[1] / math.fabs(step[0])]
+
+        else:
+            if step[1] >= 0:
+                step = [step[0] / math.fabs(step[1]), 1]
+            else:
+                step = [step[0] / math.fabs(step[1]), -1]
+
+        blocked = False
+        for i in range(pointsNeeded + 1):  # Creates points between graph and solitary point
+            for j in range(STEP_DISTANCE):  # Check if there are walls between points
+                coordX = round(newPoints[i][0] + step[0] * j)
+                coordY = round(newPoints[i][1] + step[1] * j)
+
+                if coordX == a[0] and coordY == a[1]:
+                    break
+                if coordY >= len(img) or coordX >= len(img[0]):
+                    break
+                if img[int(coordY)][int(coordX)][0] * 255 < 255:
+                    blocked = True
+                if blocked:
+                    break
+
+            if blocked:
+                break
+            if not (coordX == a[0] and coordY == a[1]):
+                newPoints.append(
+                    [newPoints[i][0] + (step[0] * STEP_DISTANCE), newPoints[i][1] + (step[1] * STEP_DISTANCE)])
+
+        if not blocked:
+            newPoints.append([a[0], a[1]])
+        return newPoints
+
+    def findNearestPoint(points, point):
+        best = (sys.maxsize, sys.maxsize, sys.maxsize)
+        for p in points:
+            if p == point:
+                continue
+            dist = math.sqrt((p[0] - point[0]) ** 2 + (p[1] - point[1]) ** 2)
+            if dist < best[2]:
+                best = (p[0], p[1], dist)
+        return (best[0], best[1])
+
+    karte = np.ones([80, 80, 3], dtype=int)
+
+    # Koordinatentransformation
+    initialObstacles = [[int(x[0] * 10), int(x[1] * 10)] for x in initialObstacles]
+    initialPose = [initialPose[0] * 10, initialPose[1] * 10]
+    initialFinalTarget = [initialFinalTarget[0] * 10, initialFinalTarget[1] * 10]
+
+    initialObstacles = [[int(x[0] + 40), int(x[1] - 40)] for x in initialObstacles]
+    initialPose = [initialPose[0] + 40, initialPose[1] - 40]
+    initialFinalTarget = [initialFinalTarget[0] + 40, initialFinalTarget[1] - 40]
+
+    initialObstacles = [[int(x[0]), int(x[1] * (-1))] for x in initialObstacles]
+    initialPose = [int(initialPose[0]), int(initialPose[1] * -1)]
+    initialFinalTarget = [int(initialFinalTarget[0]), int(initialFinalTarget[1] * -1)]
+
+    # Karte Hindernisse einzeichnen
+    rot = np.array(0, dtype=int)
+    gruen = np.array(0, dtype=int)
+    blau = np.array(0, dtype=int)
+
+    for k in initialObstacles:
+        karte[k[1], k[0], 0] = rot;
+        karte[k[1], k[0], 1] = gruen;
+        karte[k[1], k[0], 2] = blau;
+
+        karte[k[1] + 1, k[0] + 0, 0] = rot;
+        karte[k[1] + 1, k[0] + 0, 1] = gruen;
+        karte[k[1] + 1, k[0] + 0, 2] = blau;
+
+        karte[k[1] - 0, k[0] + 1, 0] = rot;
+        karte[k[1] - 0, k[0] + 1, 1] = gruen;
+        karte[k[1] - 0, k[0] + 1, 2] = blau;
+
+        karte[k[1] + 0, k[0] - 1, 0] = rot;
+        karte[k[1] + 0, k[0] - 1, 1] = gruen;
+        karte[k[1] + 0, k[0] - 1, 2] = blau;
+
+        karte[k[1] - 1, k[0] - 0, 0] = rot;
+        karte[k[1] - 1, k[0] - 0, 1] = gruen;
+        karte[k[1] - 1, k[0] - 0, 2] = blau;
+
+    #Plotten als PNG speichern
+    from PIL import Image
+    im = Image.fromarray((karte * 255).astype(np.uint8))
+    im.save('karte.png')
+
+    print('Loading map... with file \'', MAP_IMG, '\'')
+    img = imread(MAP_IMG)
+    fig = ppl.gcf()
+    fig.clf()
+    ax = fig.add_subplot(1, 1, 1)
+    ax.imshow(img, cmap=cm.Greys_r)
+    ax.axis('image')
+    ppl.draw()
+    print('Map is', len(img[0]), 'x', len(img))
+    start = initialPose
+    goal = initialFinalTarget
+
+    path = rapidlyExploringRandomTree(ax, img, start, goal, seed=SEED)
+
+    # Ruecktransformation
+    path1 = [[x[0], x[1] * (-1)] for x in path]
+    path2 = [[(x[0] - 40), (x[1] + 40)] for x in path1]
+    path3 = [[(x[0] / 10), (x[1] / 10)] for x in path2]
+
+    path3 = [[(x[0]), x[1], 0, 0, 0, 0, 0] for x in path3]
+
+    print("Umgerechneter Pfad", path3)
+
+    if len(sys.argv) > 2:
+        print('Only one argument is needed')
+    elif len(sys.argv) > 1:
+        if os.path.isfile(sys.argv[1]):
+            MAP_IMG = sys.argv[1]
+        else:
+            print(sys.argv[1], 'is not a file')
+
+    pathIndCntr = 0
+    
+    return path3, pathIndCntr
+
+#=============[Evaluation functions]===========================================
+collisionCntr = 0
+recalcCntr = 0
+def updateEval_RobotCollisions(detector):
+    global collisionCntr
+    collision = np.nan_to_num(detector.getValue(), nan=0)
+    collisionCntr += int(collision)
+    return bool(collision)
+
+#======================================[MAIN Execution]========================
+if __name__ == "__main__":
+    plotting = False
+    nPlot = 80
+    festgefahren = 0
+    #Only increase this value if the simulation is running slowly
+    TIME_STEP = 64    
+    
+    #%%=============[DO NOT CHANGE THIS PART OF THE SCRIPT]==================
+    loopCntr = 0                                                            # 
+    turtle = rc.turtlebotController(TIME_STEP, 
+        poseGoal_tcs=np.array([-0.863, -2.0, 0.0, 0.0, 0.0, 1.0, 3.14159])) #
+    detector = turtle.robot.getDevice("collisionDetector")                  #
+    detector.enable(TIME_STEP)                                              #
+                                                                            #
+    #The map will be initialized after the first timestep (Transmission)    #
+    turtle.robot.step(turtle.TIME_STEP)                                     #
+    turtle.update()                                                         #                                                              
+
+    #The map will have the dynamic objects after the second timestep        #
+    turtle.robot.step(turtle.TIME_STEP)                                     #
+    turtle.update()                                                         #
+    ScenarioFinalTarget = findTargetPosition(turtle)                        #
+                                                                            # 
+    if plotting:
+        mg.plotting_GM_plotly(turtle.mapGenerator)
+    #DO NOT CHANGE OR REMOVE THIS FUNCTION CALL AND POSITION                #
+    waitRandomTimeSteps(turtle)                                             #
+    #===============[From here you can change the script]====================
+    #%%
+    #here you should insert a function, which plans a path; the functions has to return a path and related index
+    try:
+        path, pathIndCntr = planInitialPath(turtle)
+    except TypeError:
+        print("Erste Pfadplanung nicht erfolgreich, neustart...")
+        try:
+            path, pathIndCntr = planInitialPath(turtle)
+        except TypeError:
+            print("Zweite Pfadplanung nicht erfolgreich, neustart...")
+            try:
+                path, pathIndCntr = planInitialPath(turtle)
+            except TypeError:
+                print("Dritte Pfadplanung nicht erfolgreich, neustart...")
+                exit()
+
+    turtle.setPoseGoal(path[pathIndCntr])
+    startTime = turtle.robot.getTime()
+
+    inhibitCntr = 0
+    while turtle.robot.step(turtle.TIME_STEP) != -1:
+    #%%===[DO NOT CHANGE THIS PART OF THE LOOP]==========================
+        loopCntr += 1                                                       #
+        turtle.update()
+
+        collision = checkForPossibleCollisions(turtle, findRobotPosition(turtle), collisionCntr)
+
+        if ( (plotting) & (loopCntr % nPlot == 0)):                         #
+            mg.plotting_GM_plotly(turtle.mapGenerator)                      #
+        #====[From here you can change the loop]=============================
+        #%%                
+        #Follow the static path towards the index pathIndCntr in the path
+        inhibitCntr = max(0, inhibitCntr - 1)
+
+        if(collision == False):
+            pathIndCntr = staticPathTracking(turtle, path, pathIndCntr)
+
+        if(collision == True):
+            print("Knallt")
+            turtle.stop()
+            festgefahren += 1
+
+            if(festgefahren == 10):
+                #Berechnen neue Pos
+                vorherigePos = path[pathIndCntr-1]
+                neueRichtung = [vorherigePos[0] / 2, vorherigePos[1] / 2, 0, 0, 0, 0, 0]
+                path.insert(pathIndCntr, neueRichtung)
+
+                #Fahre neue Pos an bis du da bist
+                #Wenn du da bist festgefahren 0 und hoffentlich keine Collsion mehr
+                recalcCntr += 1
+                inhibitCntr = 15
+                festgefahren = 0
+                collision = False
+
+        #This is the exit condition. Changing this is not recommended
+        if(pathIndCntr == -1):
+            break
+    #End while
+    #%%
+    print("Simulation ended")
+    print("Timesteps with collisions: ", collisionCntr)
+    print("Recalculations done: ", recalcCntr)
+    print("Simulationtime: ", turtle.robot.getTime() - startTime)
+    print("")
+    print("Recalculation")
+    print("Timesteps with collisions: ", collisionCntr)
+    print("Recalculations done: ", recalcCntr)
+    print("Simulationtime: ", turtle.robot.getTime() - startTime)
+
+    lastStateObstacles = np.array(findObstaclePositions(turtle))
+    lastStateRobotPose = np.array(findRobotPosition(turtle))
+        
+    trackRobot = np.array(turtle.trackRobot)
+    plt.scatter(lastStateObstacles[..., 0], lastStateObstacles[..., 1])
+    plt.scatter(lastStateRobotPose[..., 0], lastStateRobotPose[..., 1])
+    
+    plt.plot(trackRobot[..., 0], trackRobot[..., 1])
+    plt.scatter(turtle.poseGoal[0], turtle.poseGoal[1])
+    plt.scatter(turtle.mapGenerator.finalTarget[0], turtle.mapGenerator.finalTarget[1])
+    plt.show()
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/map.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/map.py
new file mode 100644
index 0000000..379645d
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/map.py
@@ -0,0 +1,24 @@
+#Map erstellen
+
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+img = cap.read()
+#height, width = img.shape[:2]
+
+success, img = cap.read()
+gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+mask[mask == 255] = 87
+
+mask = np.array(mask, dtype=np.uint8).view('S2').squeeze()
+
+mask[mask == b'WW'] = 'W'
+
+print(mask)
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/maperstellen.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/maperstellen.py
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node copy.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node copy.py
new file mode 100644
index 0000000..29f2473
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node copy.py	
@@ -0,0 +1,183 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime
+
+
+class MyNode(Node):
+
+    def __init__(self):
+        super().__init__("sphero_mini")
+        self.publisher_ = self.create_publisher(String,"Imu",5)
+        #self.get_logger().info("Hello from ROS2")
+    
+    def connect(self):
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        #    cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+        #print(i)
+
+        #self.publisher_.publish(i)
+
+
+        
+def main(args = None):
+
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+    thread.start()
+    rate = node.create_rate(2)
+
+    try:
+        while rclpy.ok():
+
+            sphero.configureSensorMask(
+                IMU_yaw=True,
+                IMU_pitch=True,
+                IMU_roll=True,
+                IMU_acc_y=True,
+                IMU_acc_z=True,
+                IMU_acc_x=True,
+                IMU_gyro_x=True,
+                IMU_gyro_y=True,
+                #IMU_gyro_z=True 
+                )
+            sphero.configureSensorStream()
+
+            sensors_values = node.get_sensors_data(sphero)
+            #rclpy.logdebug(sensors_values)
+            node.publish_imu(sensors_values, node)
+            sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn LEDs green
+
+            # Aiming:
+            sphero.setLEDColor(red = 0, green = 0, blue = 0) # Turn main LED off
+            sphero.stabilization(False) # Turn off stabilization
+            sphero.setBackLEDIntensity(255) # turn back LED on
+            sphero.wait(3) # Non-blocking pau`se
+            sphero.resetHeading() # Reset heading
+            sphero.stabilization(True) # Turn on stabilization
+            sphero.setBackLEDIntensity(0) # Turn back LED off
+
+            # Move around:
+            sphero.setLEDColor(red = 0, green = 0, blue = 255) # Turn main LED blue
+            sphero.roll(100, 0)      # roll forwards (heading = 0) at speed = 50
+
+            sphero.wait(3)         # Keep rolling for three seconds
+
+            sphero.roll(0, 0)       # stop
+            sphero.wait(1)          # Allow time to stop
+
+            sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn main LED green
+            sphero.roll(-100, 0)     # Keep facing forwards but roll backwards at speed = 50
+            sphero.wait(3)          # Keep rolling for three seconds
+
+            sphero.roll(0, 0)       # stop
+            sphero.wait(1)          # Allow time to stop
+    
+            rate.sleep()
+
+    except KeyboardInterrupt:
+        pass
+
+    rclpy.shutdown()
+    thread.join()
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py
new file mode 100644
index 0000000..8906b23
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py
@@ -0,0 +1,766 @@
+#!/usr/bin/env python3
+############################################################################
+#%% Imports
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Imu
+import threading
+from geometry_msgs.msg import Quaternion, Vector3
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini 
+import cv2
+import time
+import queue
+import matplotlib.pyplot as plt
+############################################################################
+#%% Blob Detector / Globale Variablen
+detector = cv2.SimpleBlobDetector()
+ 
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+params.filterByArea = True
+params.minArea = 10
+params.maxArea = 200
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+#params.filterByInertia = True
+#params.minInertiaRatio = 0.01
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+############################################################################
+#%% Class Video Capture
+# Bufferless VideoCapture
+# Quelle ?
+class VideoCapture:
+  def __init__(self, name):
+    self.cap = cv2.VideoCapture(name)
+    self.q = queue.Queue()
+    t = threading.Thread(target=self._reader)
+    t.daemon = True
+    t.start()
+  # read frames as soon as they are available, keeping only most recent one
+  def _reader(self):
+    while True:
+        ret, frame = self.cap.read()
+        #cv2.imshow("Cap", frame)
+
+        if not ret:
+            break
+        if not self.q.empty():
+            try:
+                self.q.get_nowait()   # discard previous (unprocessed) frame
+            except queue.Empty:
+                pass
+        self.q.put(frame)
+
+  def read(self):
+    return self.q.get()
+############################################################################
+#%% Class Sphero Node
+class MyNode(Node):
+    def __init__(self):
+        super().__init__("sphero_mini")
+    
+    def connect(self):
+        #Automatisch MAC-Adresse laden
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        # cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def get_pos(self, cap, height):
+        #zeitanfang = time.time()
+        
+        success = False
+
+        while(success == False):
+            try:
+                img = cap.read()
+
+                gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+                keypoints = detector.detect(gray)
+
+                for keyPoint in keypoints:
+                    x = keyPoint.pt[0]
+                    y = keyPoint.pt[1]
+                    success = True
+
+                xTrans, yTrans = self.calc_trans(x,y, height)
+            except Exception:
+                continue
+
+        #print("Blob X: %f Blob Y: %f" %(x,y))
+        #zeitende = time.time()
+        #print("Dauer Programmausführung:",(zeitende-zeitanfang))
+        #print("Get_Pos: X,Y:", xTrans,yTrans)
+
+        return xTrans,yTrans
+
+    def calc_offset(self, sphero, cap, height):
+        sphero.roll(100,0)
+        sphero.wait(1)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.get_pos(cap, height)
+        print("calc_offset: Ref Punkt x,y", ref)
+
+        sphero.wait(1)
+        sphero.roll(100,180)
+        sphero.wait(1)
+        sphero.roll(0,0)
+
+        startpunkt = self.get_pos(cap, height)
+        print("calc_offset: Startpunkt x,y", startpunkt)
+
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+
+        phi = np.arctan2(start_ref[1],start_ref[0])
+        phi = np.degrees(phi)
+        phi = int(-phi)
+        
+        print("Phi ohne alles:", phi)
+
+        phi = self.phi_in_range(phi)   
+
+        print("Calc_Offset: ", phi)
+
+        return phi
+
+    def calc_av(self,istPos, sollPos, cap, height):    
+        startPos = istPos
+
+        startPos = np.array(startPos)
+        sollPos = np.array(sollPos)
+
+        pktSpheroKord = sollPos - startPos
+
+        phi = np.arctan2(pktSpheroKord[1], pktSpheroKord[0])
+        phi = np.degrees(phi)
+
+        phiZiel = int(phi)
+
+        phiZiel = self.phi_in_range(phiZiel)
+
+        v = 100
+
+        #print("Calc_AV: a,v", phiZiel, v)
+
+        return phiZiel, v
+    
+    def drive_to(self,sphero, targetPos, aOffset, cap, height):
+        dmin = 20
+        pos = self.get_pos(cap, height)
+        pos = np.array(pos)
+
+        diff = targetPos - pos
+
+        d = np.linalg.norm(diff, ord = 2)
+
+        ar = []
+        ar.append(0)
+            
+        i = 1
+
+        while d > dmin:
+            a,v = self.calc_av(pos,targetPos, cap, height)
+
+            aR = -aOffset - a #Fallunterscheidung?
+            ar.append((self.phi_in_range(aR)))
+            
+            #Fahrbefehl
+            if(ar[i] != ar[i-1]):
+                sphero.roll(v, ar[i])
+                sphero.wait(0.05)
+            else:
+                sphero.wait(0.05)
+                
+            #Aktuelle Pos
+            pos = self.get_pos(cap, height)
+            pos = np.array(pos)
+            
+            #Abweichung
+            diff = targetPos - pos
+            diff = np.array(diff)
+            d = np.linalg.norm(diff, ord = 2)
+
+            i = i + 1
+
+        sphero.roll(0,0)
+        print("Ziel Erreicht")
+
+        return
+
+    def calc_trans(self,x,y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+    
+    def phi_in_range(self,phi):    
+        while(phi < 0):
+            phi = phi + 360 
+        while(phi > 360):
+            phi = phi - 360 
+        return phi  
+############################################################################
+#%% Class Wavefrontplanner
+class waveFrontPlanner:
+    ############################################################################
+    # WAVEFRONT ALGORITHM
+    # Adapted to Python Code By Darin Velarde
+    # Fri Jan 29 13:56:53 PST 2010
+    # from C code from John Palmisano 
+    # (www.societyofrobots.com)
+    ############################################################################
+
+    def __init__(self, mapOfWorld, slow=False):
+        self.__slow = slow
+        self.__mapOfWorld = mapOfWorld
+        if str(type(mapOfWorld)).find("numpy") != -1:
+            #If its a numpy array
+            self.__height, self.__width = self.__mapOfWorld.shape
+        else:
+            self.__height, self.__width = len(self.__mapOfWorld), len(self.__mapOfWorld[0])
+
+        self.__nothing = 000
+        self.__wall = 999
+        self.__goal = 1
+        self.__path = "PATH"
+
+        self.__finalPath = []
+
+        #Robot value
+        self.__robot = 254
+        #Robot default Location
+        self.__robot_x = 0
+        self.__robot_y = 0
+
+        #default goal location
+        self.__goal_x = 8
+        self.__goal_y = 9
+
+        #temp variables
+        self.__temp_A = 0
+        self.__temp_B = 0
+        self.__counter = 0
+        self.__steps = 0 #determine how processor intensive the algorithm was
+
+        #when searching for a node with a lower value
+        self.__minimum_node = 250
+        self.__min_node_location = 250
+        self.__new_state = 1
+        self.__old_state = 1
+        self.__reset_min = 250 #above this number is a special (wall or robot)
+    ###########################################################################
+
+    def setRobotPosition(self, x, y):
+        """
+        Sets the robot's current position
+
+        """
+
+        self.__robot_x = x
+        self.__robot_y = y
+    ###########################################################################
+
+    def setGoalPosition(self, x, y):
+        """
+        Sets the goal position.
+
+        """
+
+        self.__goal_x = x
+        self.__goal_y = y
+    ###########################################################################
+
+    def robotPosition(self):
+        return  (self.__robot_x, self.__robot_y)
+    ###########################################################################
+
+    def goalPosition(self):
+        return  (self.__goal_x, self.__goal_y)
+    ###########################################################################
+
+    def run(self, prnt=False):
+        """
+        The entry point for the robot algorithm to use wavefront propagation.
+
+        """
+
+        path = []
+        while self.__mapOfWorld[self.__robot_x][self.__robot_y] != self.__goal:
+            if self.__steps > 10000:
+                print ("Cannot find a path.")
+                return
+            #find new location to go to
+            self.__new_state = self.propagateWavefront()
+            #update location of robot
+            if self.__new_state == 1:
+                self.__robot_x -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" % (self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 2:
+                self.__robot_y += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 3:
+                self.__robot_x += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 4:
+                self.__robot_y -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            self.__old_state = self.__new_state
+        msg = "Found the goal in %i steps:\n" % self.__steps
+        msg += "mapOfWorld size= %i %i\n\n" % (self.__height, self.__width)
+        if prnt:
+            print(msg)
+            self.printMap()
+        return path
+    ###########################################################################
+
+    def propagateWavefront(self, prnt=False):
+        self.unpropagate()
+        #Old robot location was deleted, store new robot location in mapOfWorld
+        self.__mapOfWorld[self.__robot_x][self.__robot_y] = self.__robot
+        self.__path = self.__robot
+        #start location to begin scan at goal location
+        self.__mapOfWorld[self.__goal_x][self.__goal_y] = self.__goal
+        counter = 0
+        while counter < 200:  #allows for recycling until robot is found
+            x = 0
+            y = 0
+            #time.sleep(0.00001)
+            #while the mapOfWorld hasnt been fully scanned
+            while x < self.__height and y < self.__width:
+                #if this location is a wall or the goal, just ignore it
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal:
+                    #a full trail to the robot has been located, finished!
+                    minLoc = self.minSurroundingNodeValue(x, y)
+                    if minLoc < self.__reset_min and \
+                        self.__mapOfWorld[x][y] == self.__robot:
+                        if prnt:
+                            print("Finished Wavefront:\n")
+                            self.printMap()
+                        # Tell the robot to move after this return.
+                        return self.__min_node_location
+                    #record a value in to this node
+                    elif self.__minimum_node != self.__reset_min:
+                        #if this isnt here, 'nothing' will go in the location
+                        self.__mapOfWorld[x][y] = self.__minimum_node + 1
+                #go to next node and/or row
+                y += 1
+                if y == self.__width and x != self.__height:
+                    x += 1
+                    y = 0
+            #print self.__robot_x, self.__robot_y
+            if prnt:
+                print("Sweep #: %i\n" % (counter + 1))
+                self.printMap()
+            self.__steps += 1
+            counter += 1
+        return 0
+    ###########################################################################
+
+    def unpropagate(self):
+        """
+        clears old path to determine new path
+        stay within boundary
+
+        """
+
+        for x in range(0, self.__height):
+            for y in range(0, self.__width):
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal and \
+                    self.__mapOfWorld[x][y] != self.__path:
+                    #if this location is a wall or goal, just ignore it
+                    self.__mapOfWorld[x][y] = self.__nothing #clear that space
+    ###########################################################################
+
+    def minSurroundingNodeValue(self, x, y):
+        """
+        this method looks at a node and returns the lowest value around that
+        node.
+
+        """
+
+        #reset minimum
+        self.__minimum_node = self.__reset_min
+        #down
+        if x < self.__height -1:
+            if self.__mapOfWorld[x + 1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x + 1][y] != self.__nothing:
+                #find the lowest number node, and exclude empty nodes (0's)
+                self.__minimum_node = self.__mapOfWorld[x + 1][y]
+                self.__min_node_location = 3
+        #up
+        if x > 0:
+            if self.__mapOfWorld[x-1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x-1][y] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x-1][y]
+                self.__min_node_location = 1
+        #right
+        if y < self.__width -1:
+            if self.__mapOfWorld[x][y + 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y + 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y + 1]
+                self.__min_node_location = 2
+        #left
+        if y > 0:
+            if self.__mapOfWorld[x][y - 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y - 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y-1]
+                self.__min_node_location = 4
+        return self.__minimum_node
+    ###########################################################################
+
+    def printMap(self):
+        """
+        Prints out the map of this instance of the class.
+
+        """
+
+        msg = ''
+        for temp_B in range(0, self.__height):
+            for temp_A in range(0, self.__width):
+                if self.__mapOfWorld[temp_B][temp_A] == self.__wall:
+                    msg += "%04s" % "[#]"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__robot:
+                    msg += "%04s" % "-"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__goal:
+                    msg += "%04s" % "G"
+                else:
+                    msg += "%04s" % str(self.__mapOfWorld[temp_B][temp_A])
+            msg += "\n\n"
+        msg += "\n\n"
+        print(msg)
+        #
+        if self.__slow == True:
+            time.sleep(0.05)
+
+    def plotMap(self,img,path):
+        #Programm Koordinaten
+        print("Plotten")
+
+        imgTrans = cv2.transpose(img) # X und Y-Achse im Bild tauschen
+        imgPlot, ax1 = plt.subplots()
+        
+        ax1.set_title('Programm Koordinaten')
+        ax1.imshow(imgTrans)
+        ax1.set_xlabel('[px]')
+        ax1.set_ylabel('[px]')
+        ax1.scatter(path[:,0], path[:,1], color='r')
+        
+        #Bild Koordinaten
+        imgPlot2, ax2 = plt.subplots()
+        ax2.set_title('Bild Koordinaten')
+        ax2.set_xlabel('[px]')
+        ax2.set_ylabel('[px]')
+        ax2.imshow(img)
+        ax2.scatter(path[:,1], path[:,0], color='r')
+
+        plt.show()
+
+        return
+    
+    def getPathWelt(self,path,height,Mapobj):
+        
+        pathWeltX, pathWeltY = Mapobj.calc_trans_welt(path[:,1], path[:,0], height)
+        pathEckenX = []
+        pathEckenY = []
+
+        for i,px in enumerate(pathWeltX):
+            if (i < len(pathWeltX)-1) & (i > 0):
+                if px != pathWeltX[i+1]:
+                    if pathWeltY[i]!=pathWeltY[i-1]:
+                        pathEckenX.append(px)
+                        pathEckenY.append(pathWeltY[i])
+                if pathWeltY[i] != pathWeltY[i+1]:
+                    if pathWeltX[i]!=pathWeltX[i-1]:
+                        pathEckenX.append(px)
+                        pathEckenY.append(pathWeltY[i])
+                        
+        pathEckenX.append(pathWeltX[-1])
+        pathEckenY.append(pathWeltY[-1])
+                        
+
+        uebergabePath = []
+        for i in range(0,len(pathEckenX)):
+            uebergabePath.append((pathEckenX[i],pathEckenY[i]))
+
+        print("Ecken: ", uebergabePath)
+
+        return uebergabePath
+
+############################################################################
+#%% Class Map
+class mapCreate:   
+    ############################################################################
+ 
+    def create_map(self, scale, cap):
+
+        # Map erstellen
+
+        # Img Objekt
+        #cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+        img = cap.read()
+        
+        #Karte von Bild
+        #img = cv2.imread("D:/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/map/map.jpg")
+        print('Original Dimensions : ',img.shape)
+        
+        scale_percent = 100-scale # percent of original size
+        width = int(img.shape[1] * scale_percent / 100)
+        height = int(img.shape[0] * scale_percent / 100)
+        dim = (width, height)
+
+        # resize image
+        resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
+        print('Resized Dimensions : ',resized.shape)
+
+        gray = cv2.cvtColor(resized, cv2.COLOR_RGB2GRAY)
+        mask = cv2.inRange(gray, np.array([50]), np.array([255]))
+
+        plt.plot(mask)
+
+        mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+        mask_list= np.ndarray.tolist(mask)
+
+        #Markiere alle leeren Zellen mit 000 und alle Zellen mit Hinderniss mit 999
+        for i in range(0,mask.shape[0]):
+            mapOfWorld[i] = ['999' if j > 200 else '000' for j in mask_list[i]]
+        
+        mapOfWorld = np.array(mapOfWorld, dtype = int)
+        mapOfWorldSized = mapOfWorld.copy()
+        
+        e = 1
+        #Hindernisse Größer machen
+        for i in range(0,mapOfWorld.shape[0]):
+            for j in range(0,mapOfWorld.shape[1]):
+                for r in range(0,e):
+                    try:
+                        if (mapOfWorldSized[i][j] == 999):
+                            mapOfWorld[i][j+e] = 999
+                            mapOfWorld[i+e][j] = 999
+                            mapOfWorld[i-e][j] = 999
+                            mapOfWorld[i][j-e] = 999
+                            mapOfWorld[i+e][j+e] = 999
+                            mapOfWorld[i+e][j-e] = 999
+                            mapOfWorld[i-e][j+e] = 999
+                            mapOfWorld[i-e][j-e] = 999
+                    except Exception:
+                        continue
+                    
+        return mapOfWorld,img
+    ############################################################################
+
+    def scale_koord(self, sx, sy, gx, gy,scale):
+        scale_percent = 100-scale # percent of original size
+
+        sx = int(sx*scale_percent/100)
+        sy = int(sy*scale_percent/100)
+        gx = int(gx*scale_percent/100)
+        gy = int(gy*scale_percent/100)
+        
+        return sx,sy,gx,gy
+    ############################################################################
+
+    def rescale_koord(self, path,scale):
+        scale_percent = 100-scale # percent of original size100
+
+        path = np.array(path)
+
+        for i in range(len(path)):
+            path[i] = path[i]*100/scale_percent
+
+        return path
+    ############################################################################
+
+    def calc_trans_welt(self, x, y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+###############################################################################
+#%% Main Funktion 
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+        #rate = node.create_rate(5)
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    #cap = VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+    cap = VideoCapture(4)
+    Map = mapCreate()
+
+    img = cap.read()
+    height, width = img.shape[:2]
+
+    scale = 90
+
+    sphero.setLEDColor(255,0,0)
+    sphero.wait(1)
+    sphero.setBackLEDIntensity(0)
+    sphero.stabilization(True)
+
+    aOffset = node.calc_offset(sphero, cap, height) 
+
+    sphero.wait(1)
+
+    #while(True):
+
+    mapWorld,img = Map.create_map(scale, cap)
+    height, width = img.shape[:2]
+
+    #Befehle für WaveFrontPlanner/Maperstellung
+    sy,sx = node.get_pos(cap,height) #Aktuelle Roboter Pos in Welt
+    sy, sx = node.calc_trans(sy,sx,height)
+
+    gy = int(input("Bitte geben Sie die X-Zielkoordinate im Bild Koordinatensystem ein:"))    #X-Koordinate im Weltkoordinaten System
+    gx = int(input("Bitte geben Sie die Y-Zielkoordinate im Bild Koordinatensystem ein:"))    #Y-Koordinate im Weltkordinaten System
+
+    sx,sy,gx,gy = Map.scale_koord(sx,sy,gx,gy,scale) #Kordinaten Tauschen X,Y
+
+    start = time.time()
+    planner = waveFrontPlanner(mapWorld)
+    planner.setGoalPosition(gx,gy)
+    planner.setRobotPosition(sx,sy)
+    path = planner.run(False)
+    end = time.time()
+    print("Took %f seconds to run wavefront simulation" % (end - start))
+    
+    path = Map.rescale_koord(path, scale)
+    
+    planner.plotMap(img,path)
+
+    pathWelt = planner.getPathWelt(path,height,Map)
+
+    for p in pathWelt:
+        node.drive_to(sphero,p,aOffset,cap, height)
+        sphero.wait(1)
+
+    print("Geschafft")
+
+        #if cv2.waitKey(10) & 0xFF == ord('q'):
+         #   break
+
+    rclpy.shutdown()
+############################################################################
+#%% Main
+if __name__ == '__main__':
+    main()
+############################################################################
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_alt.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_alt.py
new file mode 100644
index 0000000..3b4ea79
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_alt.py
@@ -0,0 +1,323 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime   
+import cv2
+import time
+import queue, threading, time
+
+# Set up the detector with default parameters.
+detector = cv2.SimpleBlobDetector()
+ 
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+params.filterByArea = True
+params.minArea = 10
+params.maxArea = 200
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+#params.filterByInertia = True
+#params.minInertiaRatio = 0.01
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+
+# bufferless VideoCapture
+class VideoCapture:
+  def __init__(self, name):
+    self.cap = cv2.VideoCapture(name)
+    self.q = queue.Queue()
+    t = threading.Thread(target=self._reader)
+    t.daemon = True
+    t.start()
+  # read frames as soon as they are available, keeping only most recent one
+  def _reader(self):
+    while True:
+      ret, frame = self.cap.read()
+      if not ret:
+        break
+      if not self.q.empty():
+        try:
+          self.q.get_nowait()   # discard previous (unprocessed) frame
+        except queue.Empty:
+          pass
+      self.q.put(frame)
+
+  def read(self):
+    return self.q.get()
+
+class MyNode(Node):
+
+    def __init__(self):
+        super().__init__("sphero_mini")
+    
+    def connect(self):
+        #Automatisch MAC-Adresse laden
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        # cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def get_pos(self, cap, height):
+        zeitanfang = time.time()
+        
+        img = cap.read()
+        
+        gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+        keypoints = detector.detect(gray)
+
+        for keyPoint in keypoints:
+            x = keyPoint.pt[0]
+            y = keyPoint.pt[1]
+
+            #print("Blob X: %f Blob Y: %f" %(x,y))
+
+        zeitende = time.time()
+        #print("Dauer Programmausführung:",(zeitende-zeitanfang))
+
+        xTrans, yTrans = self.calc_trans(x,y, height)
+
+        #print("Get_Pos: X,Y:", xTrans,yTrans)
+
+        return xTrans,yTrans
+
+    def calc_offset(self, sphero, cap, height):
+        sphero.roll(100,0)
+        sphero.wait(2)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.get_pos(cap, height)
+        print("calc_offset: Ref Punkt x,y", ref)
+
+        sphero.wait(1)
+        sphero.roll(100,180)
+        sphero.wait(2)
+        sphero.roll(0,0)
+
+        startpunkt = self.get_pos(cap, height)
+        print("calc_offset: Startpunkt x,y", startpunkt)
+
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+
+        phi = np.arctan2(start_ref[1],start_ref[0])
+        phi = np.degrees(phi)
+        phi = int(phi)
+        
+        print("Phi ohne alles:", phi)
+
+        if(phi < 0):
+            phi = phi + 360        
+
+        if(phi > 360):
+            phi = phi - 360  
+
+        print("Calc_Offset: ", phi)
+
+        return phi
+
+    def calc_av(self, sollPos, cap, height):
+        
+        startPos = self.get_pos(cap, height)
+
+        startPos = np.array(startPos)
+        sollPos = np.array(sollPos)
+
+        pktSpheroKord = sollPos - startPos
+
+        phi = np.arctan2(pktSpheroKord[1], pktSpheroKord[0])
+        phi = np.degrees(phi)
+
+        phiZiel = int(phi)
+
+        if(phiZiel < 0):
+            phiZiel = phiZiel + 360 
+
+        if(phi > 360):
+            phi = phi - 360  
+
+        v = 100
+
+        print("Calc_AV: a,v", phiZiel, v)
+
+        return phiZiel, v
+    
+    def drive_to(self,sphero, targetPos, aOffset, cap, height):
+        dmin = 50
+        pos = self.get_pos(cap, height)
+        pos = np.array(pos)
+
+        diff = targetPos - pos
+
+        d = np.linalg.norm(diff, ord = 2)
+
+        while d > dmin:
+            a,v = self.calc_av(targetPos, cap, height)
+            ar = aOffset + a #Fallunterscheidung?
+
+            pos = self.get_pos(cap, height)
+            pos = np.array(pos)
+            diff = targetPos - pos
+            diff = np.array(diff)
+            d = np.linalg.norm(diff, ord = 2)
+
+            sphero.roll(v, ar)
+            time.sleep(0.1)
+
+        sphero.roll(0,ar)
+
+        return
+
+    def calc_trans(self,x,y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+    
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+        rate = node.create_rate(5)
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    cap = VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+    img = cap.read()
+    height, width = img.shape[:2]
+
+    sphero.setLEDColor(255,0,0)
+    sphero.wait(1)
+    sphero.setBackLEDIntensity(100)
+    sphero.stabilization(True)
+
+    aOffset = node.calc_offset(sphero, cap, height)
+
+    sphero.roll(100,0+aOffset)
+    sphero.wait(2)
+    sphero.roll(0,0)
+
+    sphero.wait(5)
+
+    targetPos = 117,430
+
+    node.drive_to(sphero,targetPos,aOffset,cap, height)
+     
+    rclpy.shutdown()
+
+if __name__ == '__main__':
+    main()
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_komisch.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_komisch.py
new file mode 100644
index 0000000..7c5dc3e
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_komisch.py
@@ -0,0 +1,305 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime   
+import cv2
+import time
+
+    
+# Img Objekt
+cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+# Set up the detector with default parameters.
+detector = cv2.SimpleBlobDetector()
+
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+#params.filterByArea = True
+#params.minArea = 100
+#params.maxArea = 1000
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+#params.filterByInertia = True
+#params.minInertiaRatio = 0.01
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+
+class MyNode(Node):
+    #Konstrukter Node Objekt
+    def __init__(self):
+        super().__init__("sphero_mini")
+        #self.publisher_ = self.create_publisher(String,"Imu",5)
+    
+    def connect(self):
+        #Automatisch MAC-Adresse laden
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        # cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def positionauslesen(self):
+        zeitanfang = time.time()
+
+        x = (-1)
+        y = (-1)
+
+        while x < 0 and y < 0:
+
+            success, img = cap.read()
+            gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+            # Detect blobs.
+            keypoints = detector.detect(gray)
+
+            #print(keypoints)
+            for keyPoint in keypoints:
+                x = keyPoint.pt[0]
+                y = keyPoint.pt[1]
+    
+            #print("Blob X: %f Blob Y: %f" %(x,y))
+        zeitende = time.time()
+        print("Dauer Programmausführung:",(zeitende-zeitanfang))
+        return (x,y)
+
+    def ref_winkel(self, sphero):
+
+        startpunkt = self.positionauslesen()
+
+        sphero.roll(100,0)
+        sphero.wait(2)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.positionauslesen()
+
+        sphero.wait(0.5)
+        sphero.roll(100,180)
+        sphero.wait(2)
+        sphero.roll(0,0)
+
+        soll = (startpunkt[0]+100,startpunkt[1])
+        
+        soll = np.array(soll)
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+        start_soll = soll-startpunkt
+
+        y = start_ref[0] * start_soll[1] - start_ref[1] * start_soll[0]
+        x = start_ref[0] * start_soll[0] + start_ref[1] * start_soll[1]
+
+        phi = np.arctan2(y,x)
+        phi = np.degrees(phi)
+        phi = int(phi)
+        
+        if(phi < 0 ):
+            phi = phi + 360        
+
+        return phi
+
+    def fahre_ziel(self, sphero, x,y, phiAbw):
+        
+        startPos = self.positionauslesen()
+        sollPos = (x,y)
+
+        startPos = np.array(startPos)
+        sollPos = np.array(sollPos)
+
+        pktSpheroKord = sollPos - startPos
+
+        phi = np.arctan2(pktSpheroKord[1], pktSpheroKord[0])
+        phi = np.degrees(phi)
+
+        phi = int(phi)
+
+        phiZiel = phiAbw - phi
+
+        if(phiZiel < 0 ):
+            phiZiel = phiZiel + 360 
+
+        print("Winkel Sphero System ", phi)
+        
+        #sollPos = (x,y)
+        #startPos = self.positionauslesen()
+        #refPos = (startPos[0]+100,startPos[1])
+
+        #sollPos = np.array(sollPos)
+        #refPos = np.array(refPos)
+        #startPos = np.array(startPos)
+
+        #start_ref = refPos-startPos
+        #start_soll = sollPos-startPos
+
+        #y = start_ref[0] * start_soll[1] - start_ref[1] * start_soll[0]
+        #x = start_ref[0] * start_soll[0] + start_ref[1] * start_soll[1]
+
+        #phi = np.arctan2(y,x)
+        #phi = np.degrees(phi)
+        #phiZiel = phiAbw - (int(phi) * -1)
+        
+        print("Zielwinkel: ", phiZiel)
+    
+        while(not(np.allclose(startPos, sollPos, atol = 50))):
+
+            sphero.roll(100, (phiZiel))
+            
+            aktPos = self.positionauslesen()
+            aktPos = np.array(aktPos)
+
+            time.sleep(0.1)
+        
+        print("Ziel erreicht")
+
+        sphero.roll(0, (0))
+
+        return
+    
+
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+        rate = node.create_rate(5)
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+
+    sphero.setLEDColor(255,0,0)
+    sphero.wait(1)
+    sphero.setBackLEDIntensity(100)
+    sphero.stabilization(True)
+
+    #Differenzwinkel auslesen
+    phiAbw = node.ref_winkel(sphero)
+    print("Abweichender Winkel Initialfahrt:", phiAbw)
+
+    sphero.wait(5)
+    sphero.roll(100, phiAbw)
+
+    sphero.wait(5)
+    node.fahre_ziel(sphero, 94,94, phiAbw)
+
+    sphero.wait(5)
+    node.fahre_ziel(sphero, 134,462, phiAbw)
+    
+    sphero.wait(5)
+    node.fahre_ziel(sphero, 581,372, phiAbw)
+
+    sphero.wait(5)
+    node.fahre_ziel(sphero, 331,308, phiAbw)
+
+    rclpy.spin()       
+    rclpy.shutdown()
+
+if __name__ == '__main__':
+    main()
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_refwinkel.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_refwinkel.py
new file mode 100644
index 0000000..78066a4
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_refwinkel.py
@@ -0,0 +1,243 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime
+
+class MyNode(Node):
+    #Konstrukter Node Objekt
+    def __init__(self):
+        super().__init__("sphero_mini")
+        #self.publisher_ = self.create_publisher(String,"Imu",5)
+    
+    def connect(self):
+        #Automatisch MAC-Adresse laden
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        # cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def positionauslesen(self):
+        # Standard imports
+        import cv2
+        import numpy as np;
+
+        # Img Objekt
+        cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+        # Set up the detector with default parameters.
+        detector = cv2.SimpleBlobDetector()
+
+        # Setup SimpleBlobDetector parameters.
+        params = cv2.SimpleBlobDetector_Params()
+
+        # Change thresholds
+        #params.minThreshold = 5
+        #params.maxThreshold = 500
+
+        #FIlter by Color
+        params.filterByColor = True
+        params.blobColor = 255
+
+        # Filter by Area.
+        #params.filterByArea = True
+        #params.minArea = 100
+        #params.maxArea = 1000
+
+        # Filter by Circularity
+        #params.filterByCircularity = True
+        #params.minCircularity = 0.5
+        #params.maxCircularity = 1
+
+        # Filter by Convexity
+        #params.filterByConvexity = True
+        #params.minConvexity = 0.7
+        #params.maxConvexity = 1
+
+        # Filter by Inertia
+        #params.filterByInertia = True
+        #params.minInertiaRatio = 0.01
+
+        # Create a detector with the parameters
+        detector = cv2.SimpleBlobDetector_create(params)
+
+        success, img = cap.read()
+        gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+
+        # Detect blobs.
+        keypoints = detector.detect(gray)
+
+        #print(keypoints)
+        for keyPoint in keypoints:
+            x = keyPoint.pt[0]
+            y = keyPoint.pt[1]
+            #keypointss = keyPoint.sizekeyPoints
+
+            #print("Blob X: %f Blob Y: %f" %(x,y))
+
+        # Draw detected blobs as red circles.
+        # cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
+        # the size of the circle corresponds to the size of blob
+
+        im_with_keypoints = cv2.drawKeypoints(gray, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
+
+        # Show blobs
+        cv2.imshow("Keypoints", im_with_keypoints)
+
+        return (x,y)
+
+    def ref_winkel(self, sphero, x,y):
+
+        startpunkt = self.positionauslesen()
+
+        sphero.roll(100,0)
+        sphero.wait(2)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.positionauslesen()
+
+        #print(ref)
+
+        sphero.wait(0.5)
+        sphero.roll(100,180)
+        sphero.wait(2)
+        sphero.roll(0,0)
+
+        soll = (x,y)
+        
+        soll = np.array(soll)
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+        start_soll = soll-startpunkt
+        phi = np.arccos(np.dot(start_ref,start_soll) / (np.linalg.norm(start_ref)*np.linalg.norm(start_soll)))
+        return phi
+
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+        rate = node.create_rate(5)
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    #Simple Moves, Erste Bewegung erkennen
+    #try:oll = (0,0)
+    #   while rclpy.ok():
+
+            #sphero.positionauslesen()
+            #soll = 0,0
+    phi = node.ref_winkel(sphero, 0,0)
+
+    phi = np.degrees(phi)
+
+    phi = int(phi)
+
+    print("Abweihender Winkel:", phi)
+
+    sphero.wait(0.5)
+    sphero.roll(100, (0 + phi))
+    sphero.wait(2)
+    sphero.roll(0,0)
+            
+#    except KeyboardInterrupt:
+ #       pass
+
+    rclpy.shutdown()
+  #  thread.join()
+
+if __name__ == '__main__':
+    main()
+
+    #!/usr/bin/env python3
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_testfahrt.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_testfahrt.py
new file mode 100644
index 0000000..29f2473
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node_testfahrt.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python3
+
+import rclpy
+from rclpy.node import Node
+import json
+from sensor_msgs.msg import Imu
+import threading
+from std_msgs.msg import String
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from sphero_mini_controller.treiber import SpheroMini
+import datetime
+
+
+class MyNode(Node):
+
+    def __init__(self):
+        super().__init__("sphero_mini")
+        self.publisher_ = self.create_publisher(String,"Imu",5)
+        #self.get_logger().info("Hello from ROS2")
+    
+    def connect(self):
+        #conf_file_path = file("/sphero_conf.json")
+        #with open("sphero_conf.json", "r") as f:
+        #    cfg = Box(json.load(f))
+
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+        #print(i)
+
+        #self.publisher_.publish(i)
+
+
+        
+def main(args = None):
+
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+    thread.start()
+    rate = node.create_rate(2)
+
+    try:
+        while rclpy.ok():
+
+            sphero.configureSensorMask(
+                IMU_yaw=True,
+                IMU_pitch=True,
+                IMU_roll=True,
+                IMU_acc_y=True,
+                IMU_acc_z=True,
+                IMU_acc_x=True,
+                IMU_gyro_x=True,
+                IMU_gyro_y=True,
+                #IMU_gyro_z=True 
+                )
+            sphero.configureSensorStream()
+
+            sensors_values = node.get_sensors_data(sphero)
+            #rclpy.logdebug(sensors_values)
+            node.publish_imu(sensors_values, node)
+            sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn LEDs green
+
+            # Aiming:
+            sphero.setLEDColor(red = 0, green = 0, blue = 0) # Turn main LED off
+            sphero.stabilization(False) # Turn off stabilization
+            sphero.setBackLEDIntensity(255) # turn back LED on
+            sphero.wait(3) # Non-blocking pau`se
+            sphero.resetHeading() # Reset heading
+            sphero.stabilization(True) # Turn on stabilization
+            sphero.setBackLEDIntensity(0) # Turn back LED off
+
+            # Move around:
+            sphero.setLEDColor(red = 0, green = 0, blue = 255) # Turn main LED blue
+            sphero.roll(100, 0)      # roll forwards (heading = 0) at speed = 50
+
+            sphero.wait(3)         # Keep rolling for three seconds
+
+            sphero.roll(0, 0)       # stop
+            sphero.wait(1)          # Allow time to stop
+
+            sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn main LED green
+            sphero.roll(-100, 0)     # Keep facing forwards but roll backwards at speed = 50
+            sphero.wait(3)          # Keep rolling for three seconds
+
+            sphero.roll(0, 0)       # stop
+            sphero.wait(1)          # Allow time to stop
+    
+            rate.sleep()
+
+    except KeyboardInterrupt:
+        pass
+
+    rclpy.shutdown()
+    thread.join()
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/pfadplanung.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/pfadplanung.py
new file mode 100644
index 0000000..d07a2a0
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/pfadplanung.py
@@ -0,0 +1,223 @@
+
+def planInitialPath(start, goal):
+
+    from matplotlib import pyplot as ppl
+    from matplotlib import cm
+    import random, sys, math, os.path
+    from matplotlib.pyplot import imread
+
+    #Implementation of RRT
+
+    MAP_IMG = './map.jpg'  #Black and white image for a map
+    MIN_NUM_VERT = 20  # Minimum number of vertex in the graph
+    MAX_NUM_VERT = 1500  # Maximum number of vertex in the graph
+    STEP_DISTANCE = 10  # Maximum distance between two vertex
+    SEED = None  # For random numbers
+
+    def rapidlyExploringRandomTree(ax, img, start, goal, seed=None):
+        hundreds = 100
+        seed = random.seed(seed)
+        #print("Zufallsseed: ", seed)
+        points = []
+        graph = []
+        points.append(start)
+        graph.append((start, []))
+        print('Generating and conecting random points')
+        occupied = True
+        phaseTwo = False
+
+        # Phase two values (points 5 step distances around the goal point)
+        minX = max(goal[0] - 5 * STEP_DISTANCE, 0)
+        maxX = min(goal[0] + 5 * STEP_DISTANCE, len(img[0]) - 1)
+        minY = max(goal[1] - 5 * STEP_DISTANCE, 0)
+        maxY = min(goal[1] + 5 * STEP_DISTANCE, len(img) - 1)
+
+        i = 0
+        while (goal not in points) and (len(points) < MAX_NUM_VERT):
+            if (i % 100) == 0:
+                print(i, 'points randomly generated')
+
+            if (len(points) % hundreds) == 0:
+                print(len(points), 'vertex generated')
+                hundreds = hundreds + 100
+
+            while (occupied):
+                if phaseTwo and (random.random() > 0.8):
+                    point = [random.randint(minX, maxX), random.randint(minY, maxY)]
+                else:
+                    point = [random.randint(0, len(img[0]) - 1), random.randint(0, len(img) - 1)]
+
+                if (img[point[1]][point[0]][0] * 255 == 255):
+                    occupied = False
+
+            occupied = True
+
+            nearest = findNearestPoint(points, point)
+            newPoints = connectPoints(point, nearest, img)
+            addToGraph(ax, graph, newPoints, point)
+            newPoints.pop(0)  # The first element is already in the points list
+            points.extend(newPoints)
+            ppl.draw()
+            i = i + 1
+
+            if len(points) >= MIN_NUM_VERT:
+                if not phaseTwo:
+                    print('Phase Two')
+                phaseTwo = True
+
+            if phaseTwo:
+                nearest = findNearestPoint(points, goal)
+                newPoints = connectPoints(goal, nearest, img)
+                addToGraph(ax, graph, newPoints, goal)
+                newPoints.pop(0)
+                points.extend(newPoints)
+                ppl.draw()
+
+        if goal in points:
+            print('Goal found, total vertex in graph:', len(points), 'total random points generated:', i)
+
+            path = searchPath(graph, start, [start])
+
+            for i in range(len(path) - 1):
+                ax.plot([path[i][0], path[i + 1][0]], [path[i][1], path[i + 1][1]], color='g', linestyle='-',
+                        linewidth=2)
+                ppl.draw()
+
+            print('Showing resulting map')
+            print('Final path:', path)
+            print('The final path is made from:', len(path), 'connected points')
+        else:
+            path = None
+            print('Reached maximum number of vertex and goal was not found')
+            print('Total vertex in graph:', len(points), 'total random points generated:', i)
+            print('Showing resulting map')
+
+        ppl.show()
+        return path
+
+    def searchPath(graph, point, path):
+        for i in graph:
+            if point == i[0]:
+                p = i
+
+        if p[0] == graph[-1][0]:
+            return path
+
+        for link in p[1]:
+            path.append(link)
+            finalPath = searchPath(graph, link, path)
+
+            if finalPath != None:
+                return finalPath
+            else:
+                path.pop()
+
+    def addToGraph(ax, graph, newPoints, point):
+        if len(newPoints) > 1:  # If there is anything to add to the graph
+            for p in range(len(newPoints) - 1):
+                nearest = [nearest for nearest in graph if (nearest[0] == [newPoints[p][0], newPoints[p][1]])]
+                nearest[0][1].append(newPoints[p + 1])
+                graph.append((newPoints[p + 1], []))
+
+                if not p == 0:
+                    ax.plot(newPoints[p][0], newPoints[p][1], '+k')  # First point is already painted
+                ax.plot([newPoints[p][0], newPoints[p + 1][0]], [newPoints[p][1], newPoints[p + 1][1]], color='k',
+                        linestyle='-', linewidth=1)
+
+            if point in newPoints:
+                ax.plot(point[0], point[1], '.g')  # Last point is green
+            else:
+                ax.plot(newPoints[p + 1][0], newPoints[p + 1][1], '+k')  # Last point is not green
+
+    def connectPoints(a, b, img):
+        newPoints = []
+        newPoints.append([b[0], b[1]])
+        step = [(a[0] - b[0]) / float(STEP_DISTANCE), (a[1] - b[1]) / float(STEP_DISTANCE)]
+
+        # Set small steps to check for walls
+        pointsNeeded = int(math.floor(max(math.fabs(step[0]), math.fabs(step[1]))))
+
+        if math.fabs(step[0]) > math.fabs(step[1]):
+            if step[0] >= 0:
+                step = [1, step[1] / math.fabs(step[0])]
+            else:
+                step = [-1, step[1] / math.fabs(step[0])]
+
+        else:
+            if step[1] >= 0:
+                step = [step[0] / math.fabs(step[1]), 1]
+            else:
+                step = [step[0] / math.fabs(step[1]), -1]
+
+        blocked = False
+        for i in range(pointsNeeded + 1):  # Creates points between graph and solitary point
+            for j in range(STEP_DISTANCE):  # Check if there are walls between points
+                coordX = round(newPoints[i][0] + step[0] * j)
+                coordY = round(newPoints[i][1] + step[1] * j)
+
+                if coordX == a[0] and coordY == a[1]:
+                    break
+                if coordY >= len(img) or coordX >= len(img[0]):
+                    break
+                if img[int(coordY)][int(coordX)][0] * 255 < 255:
+                    blocked = True
+                if blocked:
+                    break
+
+            if blocked:
+                break
+            if not (coordX == a[0] and coordY == a[1]):
+                newPoints.append(
+                    [newPoints[i][0] + (step[0] * STEP_DISTANCE), newPoints[i][1] + (step[1] * STEP_DISTANCE)])
+
+        if not blocked:
+            newPoints.append([a[0], a[1]])
+        return newPoints
+
+    def findNearestPoint(points, point):
+        best = (sys.maxsize, sys.maxsize, sys.maxsize)
+        for p in points:
+            if p == point:
+                continue
+            dist = math.sqrt((p[0] - point[0]) ** 2 + (p[1] - point[1]) ** 2)
+            if dist < best[2]:
+                best = (p[0], p[1], dist)
+        return (best[0], best[1])
+
+    # Standard imports
+    import cv2
+    import numpy as np;
+ 
+    # Img Objekt
+    cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+    val, frame = cap.read()
+    inverted_image = np.invert(frame)
+    cv2.imwrite("map.jpg", inverted_image)
+
+    print('Loading map... with file \'', MAP_IMG, '\'')
+    img = imread(MAP_IMG)
+    fig = ppl.gcf()
+    fig.clf()
+    ax = fig.add_subplot(1, 1, 1)
+    ax.imshow(img, cmap=cm.Greys_r)
+    ax.axis('image')
+    ppl.draw()
+    print('Map is', len(img[0]), 'x', len(img))
+
+    path = rapidlyExploringRandomTree(ax, img, start, goal, seed=SEED)
+
+    if len(sys.argv) > 2:
+        print('Only one argument is needed')
+    elif len(sys.argv) > 1:
+        if os.path.isfile(sys.argv[1]):
+            MAP_IMG = sys.argv[1]
+        else:
+            print(sys.argv[1], 'is not a file')
+
+    pathIndCntr = 0
+    
+    return path, pathIndCntr
+
+start = (200,200)
+ziel = (450, 450)
+planInitialPath(start,  ziel)
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/potential_field_planning (1).py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/potential_field_planning (1).py
new file mode 100644
index 0000000..8f136b5
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/potential_field_planning (1).py	
@@ -0,0 +1,199 @@
+"""
+
+Potential Field based path planner
+
+author: Atsushi Sakai (@Atsushi_twi)
+
+Ref:
+https://www.cs.cmu.edu/~motionplanning/lecture/Chap4-Potential-Field_howie.pdf
+
+"""
+
+from collections import deque
+import numpy as np
+import matplotlib.pyplot as plt
+
+# Parameters
+KP = 5.0  # attractive potential gain
+ETA = 100.0  # repulsive potential gain
+AREA_WIDTH = 30.0  # potential area width [m]
+# the number of previous positions used to check oscillations
+OSCILLATIONS_DETECTION_LENGTH = 3
+
+show_animation = True
+
+
+def calc_potential_field(gx, gy, ox, oy, reso, rr, sx, sy):
+    minx = min(min(ox), sx, gx) - AREA_WIDTH / 2.0
+    miny = min(min(oy), sy, gy) - AREA_WIDTH / 2.0
+    maxx = max(max(ox), sx, gx) + AREA_WIDTH / 2.0
+    maxy = max(max(oy), sy, gy) + AREA_WIDTH / 2.0
+    xw = int(round((maxx - minx) / reso))
+    yw = int(round((maxy - miny) / reso))
+
+    # calc each potential
+    pmap = [[0.0 for i in range(yw)] for i in range(xw)]
+
+    for ix in range(xw):
+        x = ix * reso + minx
+
+        for iy in range(yw):
+            y = iy * reso + miny
+            ug = calc_attractive_potential(x, y, gx, gy)
+            uo = calc_repulsive_potential(x, y, ox, oy, rr)
+            uf = ug + uo
+            pmap[ix][iy] = uf
+
+    return pmap, minx, miny
+
+
+def calc_attractive_potential(x, y, gx, gy):
+    return 0.5 * KP * np.hypot(x - gx, y - gy)
+
+
+def calc_repulsive_potential(x, y, ox, oy, rr):
+    # search nearest obstacle
+    minid = -1
+    dmin = float("inf")
+    for i, _ in enumerate(ox):
+        d = np.hypot(x - ox[i], y - oy[i])
+        if dmin >= d:
+            dmin = d
+            minid = i
+
+    # calc repulsive potential
+    dq = np.hypot(x - ox[minid], y - oy[minid])
+
+    if dq <= rr:
+        if dq <= 0.1:
+            dq = 0.1
+
+        return 0.5 * ETA * (1.0 / dq - 1.0 / rr) ** 2
+    else:
+        return 0.0
+
+
+def get_motion_model():
+    # dx, dy
+    motion = [[1, 0],
+              [0, 1],
+              [-1, 0],
+              [0, -1],
+              [-1, -1],
+              [-1, 1],
+              [1, -1],
+              [1, 1]]
+
+    return motion
+
+
+def oscillations_detection(previous_ids, ix, iy):
+    previous_ids.append((ix, iy))
+
+    if (len(previous_ids) > OSCILLATIONS_DETECTION_LENGTH):
+        previous_ids.popleft()
+
+    # check if contains any duplicates by copying into a set
+    previous_ids_set = set()
+    for index in previous_ids:
+        if index in previous_ids_set:
+            return True
+        else:
+            previous_ids_set.add(index)
+    return False
+
+
+def potential_field_planning(sx, sy, gx, gy, ox, oy, reso, rr):
+
+    # calc potential field
+    pmap, minx, miny = calc_potential_field(gx, gy, ox, oy, reso, rr, sx, sy)
+
+    # search path
+    d = np.hypot(sx - gx, sy - gy)
+    ix = round((sx - minx) / reso)
+    iy = round((sy - miny) / reso)
+    gix = round((gx - minx) / reso)
+    giy = round((gy - miny) / reso)
+
+    if show_animation:
+        draw_heatmap(pmap)
+        # for stopping simulation with the esc key.
+        plt.gcf().canvas.mpl_connect('key_release_event',
+                lambda event: [exit(0) if event.key == 'escape' else None])
+        plt.plot(ix, iy, "*k")
+        plt.plot(gix, giy, "*m")
+
+    rx, ry = [sx], [sy]
+    motion = get_motion_model()
+    previous_ids = deque()
+
+    while d >= reso:
+        minp = float("inf")
+        minix, miniy = -1, -1
+        for i, _ in enumerate(motion):
+            inx = int(ix + motion[i][0])
+            iny = int(iy + motion[i][1])
+            if inx >= len(pmap) or iny >= len(pmap[0]) or inx < 0 or iny < 0:
+                p = float("inf")  # outside area
+                print("outside potential!")
+            else:
+                p = pmap[inx][iny]
+            if minp > p:
+                minp = p
+                minix = inx
+                miniy = iny
+        ix = minix
+        iy = miniy
+        xp = ix * reso + minx
+        yp = iy * reso + miny
+        d = np.hypot(gx - xp, gy - yp)
+        rx.append(xp)
+        ry.append(yp)
+
+        if (oscillations_detection(previous_ids, ix, iy)):
+            print("Oscillation detected at ({},{})!".format(ix, iy))
+            break
+
+        if show_animation:
+            plt.plot(ix, iy, ".r")
+            plt.pause(0.01)
+
+    print("Goal!!")
+
+    return rx, ry
+
+
+def draw_heatmap(data):
+    data = np.array(data).T
+    plt.pcolor(data, vmax=100.0, cmap=plt.cm.Blues)
+
+
+def main():
+    print("potential_field_planning start")
+
+    sx = 0.0  # start x position [m]
+    sy = 10.0  # start y positon [m]
+    gx = 30.0  # goal x position [m]
+    gy = 30.0  # goal y position [m]
+    grid_size = 0.5  # potential grid size [m]
+    robot_radius = 5.0  # robot radius [m]
+
+    ox = [15.0, 5.0, 20.0, 25.0]  # obstacle x position list [m]
+    oy = [25.0, 15.0, 26.0, 25.0]  # obstacle y position list [m]
+
+    if show_animation:
+        plt.grid(True)
+        plt.axis("equal")
+
+    # path generation
+    _, _ = potential_field_planning(
+        sx, sy, gx, gy, ox, oy, grid_size, robot_radius)
+
+    if show_animation:
+        plt.show()
+
+
+if __name__ == '__main__':
+    print(__file__ + " start!!")
+    main()
+    print(__file__ + " Done!!")
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/potential_field_planning.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/potential_field_planning.py
new file mode 100644
index 0000000..c28279d
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/potential_field_planning.py
@@ -0,0 +1,248 @@
+"""
+
+Potential Field based path planner
+
+author: Atsushi Sakai (@Atsushi_twi)
+
+Ref:
+https://www.cs.cmu.edu/~motionplanning/lecture/Chap4-Potential-Field_howie.pdf
+
+"""
+
+from collections import deque
+import numpy as np
+import matplotlib.pyplot as plt
+
+# Parameters
+KP = 10.0  # attractive potential gain
+ETA = 300.0  # repulsive potential gain
+AREA_WIDTH = 704.0  # potential area width [m]
+# the number of previous positions used to check oscillations
+OSCILLATIONS_DETECTION_LENGTH = 3
+
+show_animation = True
+
+px = []
+py = []
+
+def calc_potential_field(gx, gy, ox, oy, reso, rr, sx, sy):
+    minx = min(min(ox), sx, gx) - AREA_WIDTH / 2.0
+    miny = min(min(oy), sy, gy) - AREA_WIDTH / 2.0
+    maxx = max(max(ox), sx, gx) + AREA_WIDTH / 2.0
+    maxy = max(max(oy), sy, gy) + AREA_WIDTH / 2.0
+    xw = int(round((maxx - minx) / reso))
+    yw = int(round((maxy - miny) / reso))
+
+    # calc each potential
+    pmap = [[0.0 for i in range(yw)] for i in range(xw)]
+
+    for ix in range(xw):
+        x = ix * reso + minx
+
+        for iy in range(yw):
+            y = iy * reso + miny
+            ug = calc_attractive_potential(x, y, gx, gy)
+            uo = calc_repulsive_potential(x, y, ox, oy, rr)
+            uf = ug + uo
+            pmap[ix][iy] = uf
+
+    return pmap, minx, miny
+
+
+def calc_attractive_potential(x, y, gx, gy):
+    return 0.5 * KP * np.hypot(x - gx, y - gy)
+
+
+def calc_repulsive_potential(x, y, ox, oy, rr):
+    # search nearest obstacle
+    minid = -1
+    dmin = float("inf")
+    for i, _ in enumerate(ox):
+        d = np.hypot(x - ox[i], y - oy[i])
+        if dmin >= d:
+            dmin = d
+            minid = i
+
+    # calc repulsive potential
+    dq = np.hypot(x - ox[minid], y - oy[minid])
+
+    if dq <= rr:
+        if dq <= 0.1:
+            dq = 0.1
+
+        return 0.5 * ETA * (1.0 / dq - 1.0 / rr) ** 2
+    else:
+        return 0.0
+
+
+def get_motion_model():
+    # dx, dy
+    motion = [[1, 0],
+              [0, 1],
+              [-1, 0],
+              [0, -1],
+              [-1, -1],
+              [-1, 1],
+              [1, -1],
+              [1, 1]]
+
+    return motion
+
+
+def oscillations_detection(previous_ids, ix, iy):
+    previous_ids.append((ix, iy))
+
+    if (len(previous_ids) > OSCILLATIONS_DETECTION_LENGTH):
+        previous_ids.popleft()
+
+    # check if contains any duplicates by copying into a set
+    previous_ids_set = set()
+    for index in previous_ids:
+        if index in previous_ids_set:
+            return True
+        else:
+            previous_ids_set.add(index)
+    return False
+
+
+def potential_field_planning(sx, sy, gx, gy, ox, oy, reso, rr):
+
+    # calc potential field
+    pmap, minx, miny = calc_potential_field(gx, gy, ox, oy, reso, rr, sx, sy)
+
+    # search path
+    d = np.hypot(sx - gx, sy - gy)
+    ix = round((sx - minx) / reso)
+    iy = round((sy - miny) / reso)
+    gix = round((gx - minx) / reso)
+    giy = round((gy - miny) / reso)
+
+    if show_animation:
+        draw_heatmap(pmap)
+        # for stopping simulation with the esc key.
+        plt.gcf().canvas.mpl_connect('key_release_event',
+                lambda event: [exit(0) if event.key == 'escape' else None])
+        plt.plot(ix, iy, "*k")
+        plt.plot(gix, giy, "*m")
+
+    rx, ry = [sx], [sy]
+    motion = get_motion_model()
+    previous_ids = deque()
+
+    while d >= reso:
+        minp = float("inf")
+        minix, miniy = -1, -1
+        for i, _ in enumerate(motion):
+            inx = int(ix + motion[i][0])
+            iny = int(iy + motion[i][1])
+            if inx >= len(pmap) or iny >= len(pmap[0]) or inx < 0 or iny < 0:
+                p = float("inf")  # outside area
+                print("outside potential!")
+            else:
+                p = pmap[inx][iny]
+            if minp > p:
+                minp = p
+                minix = inx
+                miniy = iny
+        ix = minix
+        iy = miniy
+        xp = ix * reso + minx
+        yp = iy * reso + miny
+        d = np.hypot(gx - xp, gy - yp)
+        rx.append(xp)
+        ry.append(yp)
+
+        if (oscillations_detection(previous_ids, ix, iy)):
+            print("Oscillation detected at ({},{})!".format(ix, iy))
+            break
+
+        if show_animation:
+            px.append(ix)
+            py.append(iy)
+            plt.plot(ix, iy, ".r")
+            plt.pause(0.01)
+
+    print("Goal!!")
+
+    return rx, ry
+
+
+def draw_heatmap(data):
+    data = np.array(data).T
+    plt.pcolor(data, vmax=100.0, cmap=plt.cm.Blues)
+
+
+def create_map():
+    # Map erstellen
+    # Standard imports
+    import cv2
+    import numpy as np;
+    
+    # Img Objekt
+    #cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+    #success, img = cap.read()
+
+    gray = cv2.imread("/home/ubuntu/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/map/map.jpg",cv2.IMREAD_GRAYSCALE)
+
+    #gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+    mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+    mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+
+    mask_list= np.ndarray.tolist(mask)
+
+    for i in range(0,mask.shape[0]):
+        mapOfWorld[i] = ['W' if j > 200 else ' ' for j in mask_list[i]]
+
+    #mapOfWorld[200][200] = 'R' #Start Pos
+    #mapOfWorld[300][300] = 'G' #Ziel Pos
+
+    return mapOfWorld
+
+
+def create_obsticles(mapOfWorld):
+    ox = []
+    oy = []
+
+    mapOfWorld = np.array(mapOfWorld)
+
+    for i in range(0,mapOfWorld.shape[0]):
+        for j in range(0,mapOfWorld.shape[1]):
+            if mapOfWorld[i][j] == 'W':
+                ox.append(i)
+                oy.append(j)
+
+    return ox,oy
+
+def main():
+    print("potential_field_planning start")
+
+    mapOfWorld = create_map()
+
+    sx = 50  # start x position [m]
+    sy = 400  # start y positon [m]
+    gx = 600  # goal x position [m]
+    gy = 100  # goal y position [m]
+    grid_size = 10  # potential grid size [m]
+    robot_radius = 10  # robot radius [m]
+
+    ox, oy = create_obsticles(mapOfWorld)
+
+    if show_animation:
+        plt.grid(True)
+        plt.axis("equal")
+
+    # path generation
+    _, _ = potential_field_planning(sx, sy, gx, gy, ox, oy, grid_size, robot_radius)
+
+    if show_animation:
+        plt.show()
+
+    print("X_Pos", px)
+    print("Y_Pos", py)  
+
+if __name__ == '__main__':
+    print(__file__ + " start!!")
+    main()
+    print(__file__ + " Done!!")
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/simple_moves.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/simple_moves.py
new file mode 100644
index 0000000..b1e9f0e
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/simple_moves.py
@@ -0,0 +1,34 @@
+"""
+Simple moves
+------------
+
+This module contains functions to have the Sphero mini do some simple movements (e.g. circle).
+"""
+
+import sys
+
+def forward(sphero):
+    # Aiming:
+    sphero.setLEDColor(red = 0, green = 0, blue = 0) # Turn main LED off
+    sphero.stabilization(False) # Turn off stabilization
+    sphero.setBackLEDIntensity(255) # turn back LED on
+    sphero.wait(3) # Non-blocking pau`se
+    sphero.resetHeading() # Reset heading
+    sphero.stabilization(True) # Turn on stabilization
+    sphero.setBackLEDIntensity(0) # Turn back LED off
+
+    # Move around:
+    sphero.setLEDColor(red = 0, green = 0, blue = 255) # Turn main LED blue
+    sphero.roll(100, 0)      # roll forwards (heading = 0) at speed = 50
+
+    sphero.wait(3)         # Keep rolling for three seconds
+
+    sphero.roll(0, 0)       # stop
+    sphero.wait(1)          # Allow time to stop
+
+    sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn main LED green
+    sphero.roll(-100, 0)     # Keep facing forwards but roll backwards at speed = 50
+    sphero.wait(3)          # Keep rolling for three seconds
+
+    sphero.roll(0, 0)       # stop
+    sphero.wait(1)          # Allow time to stop
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/sphero.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/sphero.py
new file mode 100644
index 0000000..b5138d1
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/sphero.py
@@ -0,0 +1,22 @@
+import numpy as np
+def ref_winkel(sphero, soll):
+
+    startpunkt = sphero.positionsauslesen
+
+    sphero.roll(100,0)
+    sphero.wait(2)
+    sphero.roll(0,0)
+    sphero.wait(0.5)
+
+    ref =  sphero.positionsauslesen
+
+    sphero.wait(0.5)
+    sphero.roll(100,0)
+    sphero.wait(2)
+    sphero.roll(0,0)
+    
+    start_ref = ref-startpunkt
+    start_soll = soll-startpunkt
+    phi = np.arccos(start_ref*start_soll / (np.linalg.norm(start_ref)*np.linalg.norm(start_soll)))
+    return phi
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/sphero_main.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/sphero_main.py
new file mode 100644
index 0000000..37e337b
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/sphero_main.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+
+import json
+
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Imu
+from geometry_msgs.msg import Quaternion, Vector3
+from box import Box
+import numpy as np
+from core import SpheroMini
+#from simple_moves import forward
+
+def connect():
+    conf_file_path = rclpy.get_param("/conf_file_path")
+    with open(conf_file_path, 'r') as f:
+        cfg = Box(json.load(f))
+
+    # Connect:
+    sphero = SpheroMini(cfg.MAC_ADDRESS, verbosity = 4)
+    # battery voltage
+    sphero.getBatteryVoltage()
+    print(f"Bettery voltage: {sphero.v_batt}v")
+
+    # firmware version number
+    sphero.returnMainApplicationVersion()
+    print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+    return sphero
+
+
+def disconnect(sphero):
+    sphero.sleep()
+    sphero.disconnect()
+
+
+def create_quaternion(roll, pitch, yaw):
+    q = Quaternion()
+    cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+    cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+    cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+    q.w = cr * cp * cy + sr * sp * sy
+    q.x = sr * cp * cy - cr * sp * sy
+    q.y = cr * sp * cy + sr * cp * sy
+    q.z = cr * cp * sy - sr * sp * cy
+
+    return q
+
+
+def create_angular_veolocity_vector3(groll, gpitch, gyaw):
+    v = Vector3()
+    v.x = groll
+    v.y = gpitch
+    v.z = gyaw
+
+    return v
+
+
+def create_linear_acc_vector3(xacc, yacc, zacc):
+    v = Vector3()
+    v.x = xacc
+    v.y = yacc
+    v.z = zacc
+
+    return v
+
+
+def get_sensors_data(sphero):
+    return {
+        "roll": sphero.IMU_roll,
+        "pitch": sphero.IMU_pitch,
+        "yaw": sphero.IMU_yaw,
+        "groll": sphero.IMU_gyro_x,
+        "gpitch": sphero.IMU_gyro_y,
+        "xacc": sphero.IMU_acc_x,
+        "yacc": sphero.IMU_acc_y,
+        "zacc": sphero.IMU_acc_z
+    }
+    
+
+def publish_imu(pub, sensors_values):
+    i = Imu()
+
+    i.header.stamp = rclpy.Time.now()
+    i.orientation = create_quaternion(
+        roll=sensors_values["roll"],
+        pitch=sensors_values["pitch"],
+        yaw=sensors_values["yaw"]
+        )
+    i.angular_velocity = create_angular_veolocity_vector3(
+        groll=sensors_values["groll"],
+        gpitch=sensors_values["gpitch"],
+        gyaw=0  # We don't have the IMU_gyro_z
+    )
+    i.linear_acceleration = create_linear_acc_vector3(
+        xacc=sensors_values["xacc"],
+        yacc=sensors_values["yacc"],
+        zacc=sensors_values["zacc"]
+    )
+    pub.publish(i)
+
+
+def main(sphero):
+    rclpy.init_node('sphero', anonymous=True, log_level=rclpy.DEBUG)   
+    rate = rclpy.Rate(10)  # 10 Hz
+
+    pub = rclpy.Publisher("/imu", Imu, queue_size=5)
+
+    sphero.configureSensorMask(
+        IMU_yaw=True,
+        IMU_pitch=True,
+        IMU_roll=True,
+        IMU_acc_y=True,
+        IMU_acc_z=True,
+        IMU_acc_x=True,
+        IMU_gyro_x=True,
+        IMU_gyro_y=True,
+        #IMU_gyro_z=True 
+        )
+    sphero.configureSensorStream()
+
+    while not rclpy.is_shutdown():
+        sensors_values = get_sensors_data(sphero)
+        #rclpy.logdebug(sensors_values)
+        publish_imu(pub, sensors_values)
+        sphero.setLEDColor(red = 0, green = 255, blue = 0) # Turn LEDs green
+        rate.sleep()
+
+
+if __name__ == "__main__":
+    sphero = connect()
+    try:
+        main(sphero)
+    except Exception as e: # rclpy.ROSInterruptException
+        disconnect(sphero)
+        raise e
+    
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/test.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/test.py
new file mode 100644
index 0000000..b5c4cbb
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/test.py
@@ -0,0 +1,23 @@
+#Map erstellen
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+success, img = cap.read()
+
+gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+
+mask_list= np.ndarray.tolist(mask)
+
+for i in range(0,mask.shape[0]):
+    mapOfWorld[i] = ['W' if j > 200 else ' ' for j in mask_list[i]]
+
+print(mapOfWorld)
+
+
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/treiber.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/treiber.py
new file mode 100644
index 0000000..ec34350
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/treiber.py
@@ -0,0 +1,638 @@
+from bluepy.btle import Peripheral
+from bluepy import btle
+from sphero_mini_controller._constants import *
+import struct
+import time
+import sys
+
+class SpheroMini():
+    def __init__(self, MACAddr, verbosity = 4, user_delegate = None):
+        '''
+        initialize class instance and then build collect BLE sevices and characteristics.
+        Also sends text string to Anti-DOS characteristic to prevent returning to sleep,
+        and initializes notifications (which is what the sphero uses to send data back to
+        the client).
+        '''
+        self.verbosity = verbosity # 0 = Silent,
+                                   # 1 = Connection/disconnection only
+                                   # 2 = Init messages
+                                   # 3 = Recieved commands
+                                   # 4 = Acknowledgements
+        self.sequence = 1
+        self.v_batt = None # will be updated with battery voltage when sphero.getBatteryVoltage() is called
+        self.firmware_version = [] # will be updated with firware version when sphero.returnMainApplicationVersion() is called
+
+        if self.verbosity > 0:
+            print("[INFO] Connecting to ", MACAddr)
+        self.p = Peripheral(MACAddr, "random") #connect
+
+        if self.verbosity > 1:
+            print("[INIT] Initializing")
+
+        # Subscribe to notifications
+        self.sphero_delegate = MyDelegate(self, user_delegate) # Pass a reference to this instance when initializing
+        self.p.setDelegate(self.sphero_delegate)
+
+        if self.verbosity > 1:
+            print("[INIT] Read all characteristics and descriptors")
+        # Get characteristics and descriptors
+        self.API_V2_characteristic = self.p.getCharacteristics(uuid="00010002-574f-4f20-5370-6865726f2121")[0]
+        self.AntiDOS_characteristic = self.p.getCharacteristics(uuid="00020005-574f-4f20-5370-6865726f2121")[0]
+        self.DFU_characteristic = self.p.getCharacteristics(uuid="00020002-574f-4f20-5370-6865726f2121")[0]
+        self.DFU2_characteristic = self.p.getCharacteristics(uuid="00020004-574f-4f20-5370-6865726f2121")[0]
+        self.API_descriptor = self.API_V2_characteristic.getDescriptors(forUUID=0x2902)[0]
+        self.DFU_descriptor = self.DFU_characteristic.getDescriptors(forUUID=0x2902)[0]
+
+        # The rest of this sequence was observed during bluetooth sniffing:
+        # Unlock code: prevent the sphero mini from going to sleep again after 10 seconds
+        if self.verbosity > 1:
+            print("[INIT] Writing AntiDOS characteristic unlock code")
+        self.AntiDOS_characteristic.write("usetheforce...band".encode(), withResponse=True)
+
+        # Enable DFU notifications:
+        if self.verbosity > 1:
+            print("[INIT] Configuring DFU descriptor")
+        self.DFU_descriptor.write(struct.pack('<bb', 0x01, 0x00), withResponse = True)
+
+        # No idea what this is for. Possibly a device ID of sorts? Read request returns '00 00 09 00 0c 00 02 02':
+        if self.verbosity > 1:
+            print("[INIT] Reading DFU2 characteristic")
+        _ = self.DFU2_characteristic.read()
+
+        # Enable API notifications:
+        if self.verbosity > 1:
+            print("[INIT] Configuring API dectriptor")
+        self.API_descriptor.write(struct.pack('<bb', 0x01, 0x00), withResponse = True)
+
+        self.wake()
+
+        # Finished initializing:
+        if self.verbosity > 1:
+            print("[INIT] Initialization complete\n")
+
+    def disconnect(self):
+        if self.verbosity > 0:
+            print("[INFO] Disconnecting")
+        
+        self.p.disconnect()
+
+    def wake(self):
+        '''
+        Bring device out of sleep mode (can only be done if device was in sleep, not deep sleep).
+        If in deep sleep, the device should be connected to USB power to wake.
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Waking".format(self.sequence))
+        
+        self._send(characteristic=self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=powerCommandIDs["wake"],
+                   payload=[]) # empty payload
+
+        self.getAcknowledgement("Wake")
+
+    def sleep(self, deepSleep=False):
+        '''
+        Put device to sleep or deep sleep (deep sleep needs USB power connected to wake up)
+        '''
+        if deepSleep:
+            sleepCommID=powerCommandIDs["deepSleep"]
+            if self.verbosity > 0:
+                print("[INFO] Going into deep sleep. Connect USB power to wake.")
+        else:
+            sleepCommID=powerCommandIDs["sleep"]
+        self._send(characteristic=self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=sleepCommID,
+                   payload=[]) #empty payload
+
+    def setLEDColor(self, red = None, green = None, blue = None):
+        '''
+        Set device LED color based on RGB vales (each can  range between 0 and 0xFF)
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Setting main LED colour to [{}, {}, {}]".format(self.sequence, red, green, blue))
+        
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['userIO'], # 0x1a
+                  commID = userIOCommandIDs["allLEDs"], # 0x0e
+                  payload = [0x00, 0x0e, red, green, blue])
+
+        self.getAcknowledgement("LED/backlight")
+
+    def setBackLEDIntensity(self, brightness=None):
+        '''
+        Set device LED backlight intensity based on 0-255 values
+
+        NOTE: this is not the same as aiming - it only turns on the LED
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Setting backlight intensity to {}".format(self.sequence, brightness))
+
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['userIO'],
+                  commID = userIOCommandIDs["allLEDs"],
+                  payload = [0x00, 0x01, brightness])
+
+        self.getAcknowledgement("LED/backlight")
+
+    def roll(self, speed=None, heading=None):
+        '''
+        Start to move the Sphero at a given direction and speed.
+        heading: integer from 0 - 360 (degrees)
+        speed: Integer from 0 - 255
+
+        Note: the zero heading should be set at startup with the resetHeading method. Otherwise, it may
+        seem that the sphero doesn't honor the heading argument
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Rolling with speed {} and heading {}".format(self.sequence, speed, heading))
+    
+        if abs(speed) > 255:
+            print("WARNING: roll speed parameter outside of allowed range (-255 to +255)")
+
+        if speed < 0:
+            speed = -1*speed+256 # speed values > 256 in the send packet make the spero go in reverse
+
+        speedH = (speed & 0xFF00) >> 8
+        speedL = speed & 0xFF
+        headingH = (heading & 0xFF00) >> 8
+        headingL = heading & 0xFF
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['driving'],
+                  commID = drivingCommands["driveWithHeading"],
+                  payload = [speedL, headingH, headingL, speedH])
+
+        self.getAcknowledgement("Roll")
+
+    def resetHeading(self):
+        '''
+        Reset the heading zero angle to the current heading (useful during aiming)
+        Note: in order to manually rotate the sphero, you need to call stabilization(False).
+        Once the heading has been set, call stabilization(True).
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Resetting heading".format(self.sequence))
+    
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['driving'],
+                  commID = drivingCommands["resetHeading"],
+                  payload = []) #empty payload
+
+        self.getAcknowledgement("Heading")
+
+    def returnMainApplicationVersion(self):
+        '''
+        Sends command to return application data in a notification
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Requesting firmware version".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID = deviceID['systemInfo'],
+                   commID = SystemInfoCommands['mainApplicationVersion'],
+                   payload = []) # empty
+
+        self.getAcknowledgement("Firmware")
+
+    def getBatteryVoltage(self):
+        '''
+        Sends command to return battery voltage data in a notification.
+        Data printed to console screen by the handleNotifications() method in the MyDelegate class.
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Requesting battery voltage".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=powerCommandIDs['batteryVoltage'],
+                   payload=[]) # empty
+
+        self.getAcknowledgement("Battery")
+
+    def stabilization(self, stab = True):
+        '''
+        Sends command to turn on/off the motor stabilization system (required when manually turning/aiming the sphero)
+        '''
+        if stab == True:
+            if self.verbosity > 2:
+                    print("[SEND {}] Enabling stabilization".format(self.sequence))
+            val = 1
+        else:
+            if self.verbosity > 2:
+                    print("[SEND {}] Disabling stabilization".format(self.sequence))
+            val = 0
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['driving'],
+                   commID=drivingCommands['stabilization'],
+                   payload=[val])
+
+        self.getAcknowledgement("Stabilization")
+
+    def wait(self, delay):
+        '''
+        This is a non-blocking delay command. It is similar to time.sleep(), except it allows asynchronous 
+        notification handling to still be performed.
+        '''
+        start = time.time()
+        while(1):
+            self.p.waitForNotifications(0.001)
+            if time.time() - start > delay:
+                break
+
+    def _send(self, characteristic=None, devID=None, commID=None, payload=[]):
+        '''
+        A generic "send" method, which will be used by other methods to send a command ID, payload and
+        appropriate checksum to a specified device ID. Mainly useful because payloads are optional,
+        and can be of varying length, to convert packets to binary, and calculate and send the
+        checksum. For internal use only.
+
+        Packet structure has the following format (in order):
+
+        - Start byte: always 0x8D
+        - Flags byte: indicate response required, etc
+        - Virtual device ID: see _constants.py
+        - Command ID: see _constants.py
+        - Sequence number: Seems to be arbitrary. I suspect it is used to match commands to response packets (in which the number is echoed).
+        - Payload: Could be varying number of bytes (incl. none), depending on the command
+        - Checksum: See below for calculation
+        - End byte: always 0xD8
+
+        '''
+        sendBytes = [sendPacketConstants["StartOfPacket"],
+                    sum([flags["resetsInactivityTimeout"], flags["requestsResponse"]]),
+                    devID,
+                    commID,
+                    self.sequence] + payload # concatenate payload list
+
+        self.sequence += 1 # Increment sequence number, ensures we can identify response packets are for this command
+        if self.sequence > 255:
+            self.sequence = 0
+
+        # Compute and append checksum and add EOP byte:
+        # From Sphero docs: "The [checksum is the] modulo 256 sum of all the bytes
+        #                   from the device ID through the end of the data payload,
+        #                   bit inverted (1's complement)"
+        # For the sphero mini, the flag bits must be included too:
+        checksum = 0
+        for num in sendBytes[1:]:
+            checksum = (checksum + num) & 0xFF # bitwise "and to get modulo 256 sum of appropriate bytes
+        checksum = 0xff - checksum # bitwise 'not' to invert checksum bits
+        sendBytes += [checksum, sendPacketConstants["EndOfPacket"]] # concatenate
+
+        # Convert numbers to bytes
+        output = b"".join([x.to_bytes(1, byteorder='big') for x in sendBytes])
+
+        #send to specified characteristic:
+        characteristic.write(output, withResponse = True)
+
+    def getAcknowledgement(self, ack):
+        #wait up to 10 secs for correct acknowledgement to come in, including sequence number!
+        start = time.time()
+        while(1):
+            self.p.waitForNotifications(1)
+            if self.sphero_delegate.notification_seq == self.sequence-1: # use one less than sequence, because _send function increments it for next send. 
+                if self.verbosity > 3:
+                    print("[RESP {}] {}".format(self.sequence-1, self.sphero_delegate.notification_ack))
+                self.sphero_delegate.clear_notification()
+                break
+            elif self.sphero_delegate.notification_seq >= 0:
+                print("Unexpected ACK. Expected: {}/{}, received: {}/{}".format(
+                    ack, self.sequence, self.sphero_delegate.notification_ack.split()[0],
+                    self.sphero_delegate.notification_seq)
+                    )
+            if time.time() > start + 10:
+                print("Timeout waiting for acknowledgement: {}/{}".format(ack, self.sequence))
+                break
+
+# =======================================================================
+# The following functions are experimental:
+# =======================================================================
+
+    def configureCollisionDetection(self,
+                                     xThreshold = 50, 
+                                     yThreshold = 50, 
+                                     xSpeed = 50, 
+                                     ySpeed = 50, 
+                                     deadTime = 50, # in 10 millisecond increments
+                                     method = 0x01, # Must be 0x01        
+                                     callback = None):
+        '''
+        Appears to function the same as other Sphero models, however speed settings seem to have no effect. 
+        NOTE: Setting to zero seems to cause bluetooth errors with the Sphero Mini/bluepy library - set to 
+        255 to make it effectively disabled.
+
+        deadTime disables future collisions for a short period of time to avoid repeat triggering by the same
+        event. Set in 10ms increments. So if deadTime = 50, that means the delay will be 500ms, or half a second.
+        
+        From Sphero docs:
+        
+            xThreshold/yThreshold: An 8-bit settable threshold for the X (left/right) and Y (front/back) axes 
+            of Sphero.
+
+            xSpeed/ySpeed: An 8-bit settable speed value for the X and Y axes. This setting is ranged by the 
+            speed, then added to xThreshold, yThreshold to generate the final threshold value.
+        '''
+        
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring collision detection".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['configureCollision'],
+                   payload=[method, xThreshold, xSpeed, yThreshold, ySpeed, deadTime])
+
+        self.collision_detection_callback = callback
+
+        self.getAcknowledgement("Collision")
+
+    def configureSensorStream(self): # Use default values
+        '''
+        Send command to configure sensor stream using default values as found during bluetooth 
+        sniffing of the Sphero Edu app.
+
+        Must be called after calling configureSensorMask()
+        '''
+        bitfield1 = 0b00000000 # Unknown function - needs experimenting
+        bitfield2 = 0b00000000 # Unknown function - needs experimenting
+        bitfield3 = 0b00000000 # Unknown function - needs experimenting
+        bitfield4 = 0b00000000 # Unknown function - needs experimenting
+
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring sensor stream".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['configureSensorStream'],
+                   payload=[bitfield1, bitfield1, bitfield1, bitfield1])
+
+        self.getAcknowledgement("Sensor")
+
+    def configureSensorMask(self,
+                            sample_rate_divisor = 0x25, # Must be > 0
+                            packet_count = 0,
+                            IMU_pitch = False,
+                            IMU_roll = False,
+                            IMU_yaw = False,
+                            IMU_acc_x = False,
+                            IMU_acc_y = False,
+                            IMU_acc_z = False,
+                            IMU_gyro_x = False,
+                            IMU_gyro_y = False,
+                            IMU_gyro_z = False):
+
+        '''
+        Send command to configure sensor mask using default values as found during bluetooth 
+        sniffing of the Sphero Edu app. From experimentation, it seems that these are he functions of each:
+        
+        Sampling_rate_divisor. Slow data EG: Set to 0x32 to the divide data rate by 50. Setting below 25 (0x19) causes 
+                bluetooth errors        
+        
+        Packet_count: Select the number of packets to transmit before ending the stream. Set to zero to stream infinitely
+        
+        All IMU bool parameters: Toggle transmission of that value on or off (e.g. set IMU_acc_x = True to include the 
+                X-axis accelerometer readings in the sensor stream)
+        '''
+
+        # Construct bitfields based on function parameters:
+        IMU_bitfield1 = (IMU_pitch<<2) + (IMU_roll<<1) + IMU_yaw
+        IMU_bitfield2 = ((IMU_acc_y<<7) + (IMU_acc_z<<6) + (IMU_acc_x<<5) + \
+                         (IMU_gyro_y<<4) + (IMU_gyro_x<<2) + (IMU_gyro_z<<2))
+        
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring sensor mask".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensorMask'],
+                   payload=[0x00,               # Unknown param - altering it seems to slow data rate. Possibly averages multiple readings?
+                            sample_rate_divisor,       
+                            packet_count,       # Packet count: select the number of packets to stop streaming after (zero = infinite)
+                            0b00,               # Unknown param: seems to be another accelerometer bitfield? Z-acc, Y-acc
+                            IMU_bitfield1,
+                            IMU_bitfield2,
+                            0b00])              # reserved, Position?, Position?, velocity?, velocity?, Y-gyro, timer, reserved
+
+        self.getAcknowledgement("Mask")
+
+        '''
+        Since the sensor values arrive as unlabelled lists in the order that they appear in the bitfields above, we need 
+        to create a list of sensors that have been configured.Once we have this list, then in the default_delegate class, 
+        we can get sensor values as attributes of the sphero_mini class.
+        e.g. print(sphero.IMU_yaw) # displays the current yaw angle
+        '''
+
+        # Initialize dictionary with sensor names as keys and their bool values (set by the user) as values:
+        availableSensors = {"IMU_pitch" : IMU_pitch,
+                            "IMU_roll" : IMU_roll,
+                            "IMU_yaw" : IMU_yaw,
+                            "IMU_acc_y" : IMU_acc_y,
+                            "IMU_acc_z" : IMU_acc_z,
+                            "IMU_acc_x" : IMU_acc_x,
+                            "IMU_gyro_y" : IMU_gyro_y,
+                            "IMU_gyro_x" : IMU_gyro_x,
+                            "IMU_gyro_z" : IMU_gyro_z}
+        
+        # Create list of of only sensors that have been "activated" (set as true in the method arguments):
+        self.configured_sensors = [name for name in availableSensors if availableSensors[name] == True]
+
+    def sensor1(self): # Use default values
+        '''
+        Unknown function. Observed in bluetooth sniffing. 
+        '''
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensor1'],
+                   payload=[0x01])
+
+        self.getAcknowledgement("Sensor1")
+
+    def sensor2(self): # Use default values
+        '''
+        Unknown function. Observed in bluetooth sniffing. 
+        '''
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensor2'],
+                   payload=[0x00])
+
+        self.getAcknowledgement("Sensor2")
+
+# =======================================================================
+
+class MyDelegate(btle.DefaultDelegate):
+
+    '''
+    This class handles notifications (both responses and asynchronous notifications).
+    
+    Usage of this class is described in the Bluepy documentation
+    
+    '''
+
+    def __init__(self, sphero_class, user_delegate):
+        self.sphero_class = sphero_class # for saving sensor values as attributes of sphero class instance
+        self.user_delegate = user_delegate # to directly notify users of callbacks
+        btle.DefaultDelegate.__init__(self)
+        self.clear_notification()
+        self.notificationPacket = []
+
+    def clear_notification(self):
+        self.notification_ack = "DEFAULT ACK"
+        self.notification_seq = -1
+
+    def bits_to_num(self, bits):
+        '''
+        This helper function decodes bytes from sensor packets into single precision floats. Encoding follows the
+        the IEEE-754 standard.
+        '''
+        num = int(bits, 2).to_bytes(len(bits) // 8, byteorder='little')
+        num = struct.unpack('f', num)[0]
+        return num
+
+    def handleNotification(self, cHandle, data):
+        '''
+        This method acts as an interrupt service routine. When a notification comes in, this
+        method is invoked, with the variable 'cHandle' being the handle of the characteristic that
+        sent the notification, and 'data' being the payload (sent one byte at a time, so the packet
+        needs to be reconstructed)  
+
+        The method keeps appending bytes to the payload packet byte list until end-of-packet byte is
+        encountered. Note that this is an issue, because 0xD8 could be sent as part of the payload of,
+        say, the battery voltage notification. In future, a more sophisticated method will be required.
+        '''
+        # Allow the user to intercept and process data first..
+        if self.user_delegate != None:
+            if self.user_delegate.handleNotification(cHandle, data):
+                return
+        
+        #print("Received notification with packet ", str(data))
+
+        for data_byte in data: # parse each byte separately (sometimes they arrive simultaneously)
+
+            self.notificationPacket.append(data_byte) # Add new byte to packet list
+
+            # If end of packet (need to find a better way to segment the packets):
+            if data_byte == sendPacketConstants['EndOfPacket']:
+                # Once full the packet has arrived, parse it:
+                # Packet structure is similar to the outgoing send packets (see docstring in sphero_mini._send())
+                
+                # Attempt to unpack. Might fail if packet is too badly corrupted
+                try:
+                    start, flags_bits, devid, commcode, seq, *notification_payload, chsum, end = self.notificationPacket
+                except ValueError:
+                    print("Warning: notification packet unparseable ", self.notificationPacket)
+                    self.notificationPacket = [] # Discard this packet
+                    return # exit
+
+                # Compute and append checksum and add EOP byte:
+                # From Sphero docs: "The [checksum is the] modulo 256 sum of all the bytes
+                #                   from the device ID through the end of the data payload,
+                #                   bit inverted (1's complement)"
+                # For the sphero mini, the flag bits must be included too:
+                checksum_bytes = [flags_bits, devid, commcode, seq] + notification_payload
+                checksum = 0 # init
+                for num in checksum_bytes:
+                    checksum = (checksum + num) & 0xFF # bitwise "and to get modulo 256 sum of appropriate bytes
+                checksum = 0xff - checksum # bitwise 'not' to invert checksum bits
+                if checksum != chsum: # check computed checksum against that recieved in the packet
+                    print("Warning: notification packet checksum failed - ", str(self.notificationPacket))
+                    self.notificationPacket = [] # Discard this packet
+                    return # exit
+
+                # Check if response packet:
+                if flags_bits & flags['isResponse']: # it is a response
+
+                    # Use device ID and command code to determine which command is being acknowledged:
+                    if devid == deviceID['powerInfo'] and commcode == powerCommandIDs['wake']:
+                        self.notification_ack = "Wake acknowledged" # Acknowledgement after wake command
+                        
+                    elif devid == deviceID['driving'] and commcode == drivingCommands['driveWithHeading']:
+                        self.notification_ack = "Roll command acknowledged"
+
+                    elif devid == deviceID['driving'] and commcode == drivingCommands['stabilization']:
+                        self.notification_ack = "Stabilization command acknowledged"
+
+                    elif devid == deviceID['userIO'] and commcode == userIOCommandIDs['allLEDs']:
+                        self.notification_ack = "LED/backlight color command acknowledged"
+
+                    elif devid == deviceID['driving'] and commcode == drivingCommands["resetHeading"]:
+                        self.notification_ack = "Heading reset command acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["configureCollision"]:
+                        self.notification_ack = "Collision detection configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["configureSensorStream"]:
+                        self.notification_ack = "Sensor stream configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensorMask"]:
+                        self.notification_ack = "Mask configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensor1"]:
+                        self.notification_ack = "Sensor1 acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensor2"]:
+                        self.notification_ack = "Sensor2 acknowledged"
+
+                    elif devid == deviceID['powerInfo'] and commcode == powerCommandIDs['batteryVoltage']:
+                        V_batt = notification_payload[2] + notification_payload[1]*256 + notification_payload[0]*65536
+                        V_batt /= 100 # Notification gives V_batt in 10mV increments. Divide by 100 to get to volts.
+                        self.notification_ack = "Battery voltage:" + str(V_batt) + "v"
+                        self.sphero_class.v_batt = V_batt
+
+                    elif devid == deviceID['systemInfo'] and commcode == SystemInfoCommands['mainApplicationVersion']:
+                        version = '.'.join(str(x) for x in notification_payload)
+                        self.notification_ack = "Firmware version: " + version
+                        self.sphero_class.firmware_version = notification_payload
+                                                
+                    else:
+                        self.notification_ack = "Unknown acknowledgement" #print(self.notificationPacket)
+                        print(self.notificationPacket, "===================> Unknown ack packet")
+
+                    self.notification_seq = seq
+
+                else: # Not a response packet - therefore, asynchronous notification (e.g. collision detection, etc):
+                    
+                    # Collision detection:
+                    if devid == deviceID['sensor'] and commcode == sensorCommands['collisionDetectedAsync']:
+                        # The first four bytes are data that is still un-parsed. the remaining unsaved bytes are always zeros
+                        _, _, _, _, _, _, axis, _, Y_mag, _, X_mag, *_ = notification_payload
+                        if axis == 1: 
+                            dir = "Left/right"
+                        else:
+                            dir = 'Forward/back'
+                        print("Collision detected:")
+                        print("\tAxis: ", dir)
+                        print("\tX_mag: ", X_mag)
+                        print("\tY_mag: ", Y_mag)
+
+                        if self.sphero_class.collision_detection_callback is not None:
+                            self.notificationPacket = [] # need to clear packet, in case new notification comes in during callback
+                            self.sphero_class.collision_detection_callback()
+
+                    # Sensor response:
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands['sensorResponse']:
+                        # Convert to binary, pad bytes with leading zeros:
+                        val = ''
+                        for byte in notification_payload:
+                            val += format(int(bin(byte)[2:], 2), '#010b')[2:]
+                        
+                        # Break into 32-bit chunks
+                        nums = []
+                        while(len(val) > 0):
+                            num, val = val[:32], val[32:] # Slice off first 16 bits
+                            nums.append(num)
+                        
+                        # convert from raw bits to float:
+                        nums = [self.bits_to_num(num) for num in nums]
+
+                        # Set sensor values as class attributes:
+                        for name, value in zip(self.sphero_class.configured_sensors, nums):
+                            print("Setting sensor  at .", name, str(value))
+                            setattr(self.sphero_class, name, value)
+                        
+                    # Unrecognized packet structure:
+                    else:
+                        self.notification_ack = "Unknown asynchronous notification" #print(self.notificationPacket)
+                        print(str(self.notificationPacket) + " ===================> Unknown async packet")
+                        
+                self.notificationPacket = [] # Start new payload after this byte
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefront.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefront.py
new file mode 100644
index 0000000..1da3877
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefront.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+import time
+import sys
+       
+def newSearch(mapOfWorld, goal, start):
+    heap = []
+    newheap = []
+    x, y = goal
+    lastwave = 3
+    # Start out by marking nodes around G with a 3
+    moves = [(x + 1, y), (x - 1, y), (x, y - 1), (x, y + 1)]
+    
+    for move in moves:
+        if(mapOfWorld.positions[move] == ' '):
+            mapOfWorld.positions[move] = 3
+            heap.append(move)
+    for currentwave in range(4, 10000):
+        lastwave = lastwave + 1
+        while(heap != []):
+            position = heap.pop()
+            (x, y) = position
+            moves = [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]
+            #x, y = position
+            for move in moves:
+                if(mapOfWorld.positions[move] != 'W'):
+                    if(mapOfWorld.positions[move] == ' ' and mapOfWorld.positions[position] == currentwave - 1):
+                        mapOfWorld.positions[move] = currentwave
+                        newheap.append(move)
+                    if(move == start):
+                        return mapOfWorld, lastwave
+                    
+        #time.sleep(0.25)
+        #mapOfWorld.display()
+        #print heap
+        if(newheap == []):
+            print("Goal is unreachable")
+            return 1
+        heap = newheap
+        newheap = []
+          
+def printf(format, *args):
+    sys.stdout.write(format % args)    
+
+class Map(object):
+    
+    def __init__(self, xdim, ydim, positions):
+        self.xdim = xdim
+        self.ydim = ydim
+        self.positions = positions
+    def display(self):
+        printf("  ")
+        for i in range(self.ydim):
+            printf("%3s", str(i))
+        print
+        for x in range(self.xdim):
+            printf("%2s", str(x))
+            for y in range(self.ydim):
+                printf("%3s", str(self.positions[(x, y)]))
+            print
+    # Navigate though the number-populated maze
+    def nav(self, start, current):
+        self.pos = start
+        finished = False
+        
+        while(finished == False): # Run this code until we're at the goal
+            x, y = self.pos
+            self.positions[self.pos] = 'R' # Set the start on the map (this USUALLY keeps start the same)
+            #         SOUTH        NORTH         WEST      EAST
+            #           v           v             v          v      
+            moves = [(x + 1, y), (x - 1, y), (x, y - 1), (x, y + 1)] # Establish our directions
+            moveDirections = ["South", "North", "West", "East"] # Create a corresponding list of the cardinal directions
+            """ We don't want least to be 0, because then nothing would be less than it.
+                However, in order to make our code more robust, we set it to one of the values,
+                so that we're comparing least to an actual value instead of an arbitrary number (like 10).
+            """
+            # Do the actual comparing, and give us the least index so we know which move was the least
+            for w in range(len(moves)):
+                move = moves[w]
+                
+                # If the position has the current wave - 1 in it, move there.
+                if(self.positions[move] == current - 1):
+                    self.least = self.positions[move]
+                    leastIndex = w
+                # Or, if the position is the goal, stop the loop
+                elif(self.positions[move] == 'G'):
+                    finished = True
+                    leastIndex = w
+            # Decrement the current number so we can look for the next number
+            current = current - 1
+            self.positions[self.pos] = ' '
+            print( "Moved " + moveDirections[leastIndex])
+            self.pos = moves[leastIndex] # This will be converted to "move robot in x direction"
+            
+            #time.sleep(0.25)
+            #self.display()
+        # Change the goal position (or wherever we stop) to an "!" to show that we've arrived.
+        self.positions[self.pos] = '!'
+        self.display()
+# Find the goal, given the map
+def findGoal(mapOfWorld):
+    positions = mapOfWorld.positions
+    for x in range(mapOfWorld.xdim):
+        for y in range(mapOfWorld.ydim):
+            if(mapOfWorld.positions[(x, y)] == 'G'):
+                return (x, y)
+# Find the start, given the map
+def findStart(mapOfWorld):
+    positions = mapOfWorld.positions
+    for x in range(mapOfWorld.xdim):
+        for y in range(mapOfWorld.ydim):
+            if(mapOfWorld.positions[(x, y)] == 'R'):
+                
+                return (x, y)
+
+def convertMap(mapOfWorld):
+    positions = {}
+    xdim = len(mapOfWorld)
+    ydim = len(mapOfWorld[1])
+    for y in range(ydim):
+        for x in range(xdim):
+            positions[(x, y)] = mapOfWorld[x][y]
+            
+    return Map(xdim, ydim, positions)
+
+# Map erstellen
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+
+success, img = cap.read()
+
+gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
+mask = cv2.inRange(gray, np.array([90]), np.array([255]))
+
+mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+
+mask_list= np.ndarray.tolist(mask)
+
+for i in range(0,mask.shape[0]):
+    mapOfWorld[i] = ['W' if j > 200 else ' ' for j in mask_list[i]]
+
+mapOfWorld[200][200] = 'R' #Start Pos
+mapOfWorld[300][300] = 'G' #Ziel Pos
+
+print(mapOfWorld[200][200])
+print(mapOfWorld[300][300])
+
+mapOfLand = convertMap(mapOfWorld)
+mapOfLand.display()
+mapOfLand, lastwave = newSearch(mapOfLand, findGoal(mapOfLand), findStart(mapOfLand))
+mapOfLand.nav(findStart(mapOfLand), lastwave)
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefront_coverage_path_planner.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefront_coverage_path_planner.py
new file mode 100644
index 0000000..8586140
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefront_coverage_path_planner.py
@@ -0,0 +1,218 @@
+"""
+Distance/Path Transform Wavefront Coverage Path Planner
+
+author: Todd Tang
+paper: Planning paths of complete coverage of an unstructured environment
+         by a mobile robot - Zelinsky et.al.
+link: http://pinkwink.kr/attachment/cfile3.uf@1354654A4E8945BD13FE77.pdf
+"""
+
+import os
+import sys
+
+import matplotlib.pyplot as plt
+import numpy as np
+from scipy import ndimage
+
+do_animation = True
+
+
+def transform(
+        grid_map, src, distance_type='chessboard',
+        transform_type='path', alpha=0.01
+):
+    """transform
+
+    calculating transform of transform_type from src
+    in given distance_type
+
+    :param grid_map: 2d binary map
+    :param src: distance transform source
+    :param distance_type: type of distance used
+    :param transform_type: type of transform used
+    :param alpha: weight of Obstacle Transform used when using path_transform
+    """
+
+    n_rows, n_cols = grid_map.shape
+
+    if n_rows == 0 or n_cols == 0:
+        sys.exit('Empty grid_map.')
+
+    inc_order = [[0, 1], [1, 1], [1, 0], [1, -1],
+                 [0, -1], [-1, -1], [-1, 0], [-1, 1]]
+    if distance_type == 'chessboard':
+        cost = [1, 1, 1, 1, 1, 1, 1, 1]
+    elif distance_type == 'eculidean':
+        cost = [1, np.sqrt(2), 1, np.sqrt(2), 1, np.sqrt(2), 1, np.sqrt(2)]
+    else:
+        sys.exit('Unsupported distance type.')
+
+    transform_matrix = float('inf') * np.ones_like(grid_map, dtype=float)
+    transform_matrix[src[0], src[1]] = 0
+    if transform_type == 'distance':
+        eT = np.zeros_like(grid_map)
+    elif transform_type == 'path':
+        eT = ndimage.distance_transform_cdt(1 - grid_map, distance_type)
+    else:
+        sys.exit('Unsupported transform type.')
+
+    # set obstacle transform_matrix value to infinity
+    for i in range(n_rows):
+        for j in range(n_cols):
+            if grid_map[i][j] == 1.0:
+                transform_matrix[i][j] = float('inf')
+    is_visited = np.zeros_like(transform_matrix, dtype=bool)
+    is_visited[src[0], src[1]] = True
+    traversal_queue = [src]
+    calculated = [(src[0] - 1) * n_cols + src[1]]
+
+    def is_valid_neighbor(g_i, g_j):
+        return 0 <= g_i < n_rows and 0 <= g_j < n_cols \
+               and not grid_map[g_i][g_j]
+
+    while traversal_queue:
+        i, j = traversal_queue.pop(0)
+        for k, inc in enumerate(inc_order):
+            ni = i + inc[0]
+            nj = j + inc[1]
+            if is_valid_neighbor(ni, nj):
+                is_visited[i][j] = True
+
+                # update transform_matrix
+                transform_matrix[i][j] = min(
+                    transform_matrix[i][j],
+                    transform_matrix[ni][nj] + cost[k] + alpha * eT[ni][nj])
+
+                if not is_visited[ni][nj] \
+                        and ((ni - 1) * n_cols + nj) not in calculated:
+                    traversal_queue.append((ni, nj))
+                    calculated.append((ni - 1) * n_cols + nj)
+
+    return transform_matrix
+
+
+def get_search_order_increment(start, goal):
+    if start[0] >= goal[0] and start[1] >= goal[1]:
+        order = [[1, 0], [0, 1], [-1, 0], [0, -1],
+                 [1, 1], [1, -1], [-1, 1], [-1, -1]]
+    elif start[0] <= goal[0] and start[1] >= goal[1]:
+        order = [[-1, 0], [0, 1], [1, 0], [0, -1],
+                 [-1, 1], [-1, -1], [1, 1], [1, -1]]
+    elif start[0] >= goal[0] and start[1] <= goal[1]:
+        order = [[1, 0], [0, -1], [-1, 0], [0, 1],
+                 [1, -1], [-1, -1], [1, 1], [-1, 1]]
+    elif start[0] <= goal[0] and start[1] <= goal[1]:
+        order = [[-1, 0], [0, -1], [0, 1], [1, 0],
+                 [-1, -1], [-1, 1], [1, -1], [1, 1]]
+    else:
+        sys.exit('get_search_order_increment: cannot determine \
+            start=>goal increment order')
+    return order
+
+
+def wavefront(transform_matrix, start, goal):
+    """wavefront
+
+    performing wavefront coverage path planning
+
+    :param transform_matrix: the transform matrix
+    :param start: start point of planning
+    :param goal: goal point of planning
+    """
+
+    path = []
+    n_rows, n_cols = transform_matrix.shape
+
+    def is_valid_neighbor(g_i, g_j):
+        is_i_valid_bounded = 0 <= g_i < n_rows
+        is_j_valid_bounded = 0 <= g_j < n_cols
+        if is_i_valid_bounded and is_j_valid_bounded:
+            return not is_visited[g_i][g_j] and \
+                   transform_matrix[g_i][g_j] != float('inf')
+        return False
+
+    inc_order = get_search_order_increment(start, goal)
+
+    current_node = start
+    is_visited = np.zeros_like(transform_matrix, dtype=bool)
+
+    while current_node != goal:
+        i, j = current_node
+        path.append((i, j))
+        is_visited[i][j] = True
+
+        max_T = float('-inf')
+        i_max = (-1, -1)
+        i_last = 0
+        for i_last in range(len(path)):
+            current_node = path[-1 - i_last]  # get latest node in path
+            for ci, cj in inc_order:
+                ni, nj = current_node[0] + ci, current_node[1] + cj
+                if is_valid_neighbor(ni, nj) and \
+                        transform_matrix[ni][nj] > max_T:
+                    i_max = (ni, nj)
+                    max_T = transform_matrix[ni][nj]
+
+            if i_max != (-1, -1):
+                break
+
+        if i_max == (-1, -1):
+            break
+        else:
+            current_node = i_max
+            if i_last != 0:
+                print('backtracing to', current_node)
+    path.append(goal)
+
+    return path
+
+
+def visualize_path(grid_map, start, goal, path):  # pragma: no cover
+    oy, ox = start
+    gy, gx = goal
+    px, py = np.transpose(np.flipud(np.fliplr(path)))
+
+    if not do_animation:
+        plt.imshow(grid_map, cmap='Greys')
+        plt.plot(ox, oy, "-xy")
+        plt.plot(px, py, "-r")
+        plt.plot(gx, gy, "-pg")
+        plt.show()
+    else:
+        for ipx, ipy in zip(px, py):
+            plt.cla()
+            # for stopping simulation with the esc key.
+            plt.gcf().canvas.mpl_connect(
+                'key_release_event',
+                lambda event: [exit(0) if event.key == 'escape' else None])
+            plt.imshow(grid_map, cmap='Greys')
+            plt.plot(ox, oy, "-xb")
+            plt.plot(px, py, "-r")
+            plt.plot(gx, gy, "-pg")
+            plt.plot(ipx, ipy, "or")
+            plt.axis("equal")
+            plt.grid(True)
+            plt.pause(0.1)
+
+
+def main():
+    dir_path = os.path.dirname(os.path.realpath(__file__))
+    img = plt.imread(os.path.join(dir_path, 'map', 'test_2.png'))
+    img = 1 - img  # revert pixel values
+
+    start = (43, 0)
+    goal = (0, 0)
+
+    # distance transform wavefront
+    DT = transform(img, goal, transform_type='distance')
+    DT_path = wavefront(DT, start, goal)
+    visualize_path(img, start, goal, DT_path)
+
+    # path transform wavefront
+    PT = transform(img, goal, transform_type='path', alpha=0.01)
+    PT_path = wavefront(PT, start, goal)
+    visualize_path(img, start, goal, PT_path)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefrontgpt2.py b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefrontgpt2.py
new file mode 100644
index 0000000..ef76c9f
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/wavefrontgpt2.py
@@ -0,0 +1,76 @@
+from queue import Queue
+
+def wavefront_planner(map_array, start_pos, goal_pos):
+    rows = len(map_array)
+    cols = len(map_array[0])
+
+    # Überprüfe, ob Start- und Zielposition innerhalb der Karte liegen
+    if (start_pos[0] < 0 or start_pos[0] >= rows or start_pos[1] < 0 or start_pos[1] >= cols or
+            goal_pos[0] < 0 or goal_pos[0] >= rows or goal_pos[1] < 0 or goal_pos[1] >= cols):
+        raise ValueError("Start or goal position is out of bounds.")
+
+    # Erzeuge eine Kopie der Karte für den Wavefront-Algorithmus
+    wavefront_map = [[-1] * cols for _ in range(rows)]
+
+    # Definiere die Bewegungsrichtungen (4-Wege-Bewegung: oben, unten, links, rechts)
+    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
+
+    # Erzeuge eine Warteschlange für die Wellenfrontausbreitung
+    queue = Queue()
+    queue.put(goal_pos)
+
+    # Führe die Wellenfrontausbreitung durch
+    wavefront_map[goal_pos[0]][goal_pos[1]] = 0
+    while not queue.empty():
+        current_pos = queue.get()
+
+        # Überprüfe die Nachbarzellen
+        for direction in directions:
+            new_pos = (current_pos[0] + direction[0], current_pos[1] + direction[1])
+
+            # Überprüfe, ob die Nachbarzelle gültig und noch nicht besucht ist
+            if (0 <= new_pos[0] < rows and 0 <= new_pos[1] < cols and
+                    wavefront_map[new_pos[0]][new_pos[1]] == -1 and map_array[new_pos[0]][new_pos[1]] == 0):
+                wavefront_map[new_pos[0]][new_pos[1]] = wavefront_map[current_pos[0]][current_pos[1]] + 1
+                queue.put(new_pos)
+
+    # Überprüfe, ob der Startpunkt erreichbar ist
+    if wavefront_map[start_pos[0]][start_pos[1]] == -1:
+        raise ValueError("Start position is unreachable.")
+
+    # Verfolge den Pfad basierend auf der Wellenfront
+    path = [start_pos]
+    current_pos = start_pos
+    while current_pos != goal_pos:
+        next_pos = None
+        min_distance = float('inf')
+
+        for direction in directions:
+            neighbor_pos = (current_pos[0] + direction[0], current_pos[1] + direction[1])
+
+            if (0 <= neighbor_pos[0] < rows and 0 <= neighbor_pos[1] < cols and
+                    wavefront_map[neighbor_pos[0]][neighbor_pos[1]] < min_distance):
+                next_pos = neighbor_pos
+                min_distance = wavefront_map[neighbor_pos[0]][neighbor_pos[1]]
+
+        if next_pos is None:
+            raise ValueError("No path found.")
+
+        path.append(next_pos)
+        current_pos = next_pos
+
+    return path
+
+# Beispielverwendung
+map_array = [
+    [0, 0, 0, 0],
+    [0, 1, 1, 0],
+    [0, 0, 0, 0],
+    [0, 1, 1, 0],
+]
+
+start_pos = (0, 0)
+goal_pos = (1, 3)
+
+path = wavefront_planner(map_array, start_pos, goal_pos)
+print("Path:", path)
diff --git a/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/sphero_mini b/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/sphero_mini
new file mode 100644
index 0000000..01ae998
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/sphero_mini
@@ -0,0 +1,33 @@
+#!/usr/bin/python3
+# EASY-INSTALL-ENTRY-SCRIPT: 'sphero-mini-controller==0.0.0','console_scripts','sphero_mini'
+import re
+import sys
+
+# for compatibility with easy_install; see #2198
+__requires__ = 'sphero-mini-controller==0.0.0'
+
+try:
+    from importlib.metadata import distribution
+except ImportError:
+    try:
+        from importlib_metadata import distribution
+    except ImportError:
+        from pkg_resources import load_entry_point
+
+
+def importlib_load_entry_point(spec, group, name):
+    dist_name, _, _ = spec.partition('==')
+    matches = (
+        entry_point
+        for entry_point in distribution(dist_name).entry_points
+        if entry_point.group == group and entry_point.name == name
+    )
+    return next(matches).load()
+
+
+globals().setdefault('load_entry_point', importlib_load_entry_point)
+
+
+if __name__ == '__main__':
+    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
+    sys.exit(load_entry_point('sphero-mini-controller==0.0.0', 'console_scripts', 'sphero_mini')())
diff --git a/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/test_node b/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/test_node
new file mode 100644
index 0000000..42b5555
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller/test_node
@@ -0,0 +1,33 @@
+#!/usr/bin/python3
+# EASY-INSTALL-ENTRY-SCRIPT: 'sphero-mini-controller==0.0.0','console_scripts','test_node'
+import re
+import sys
+
+# for compatibility with easy_install; see #2198
+__requires__ = 'sphero-mini-controller==0.0.0'
+
+try:
+    from importlib.metadata import distribution
+except ImportError:
+    try:
+        from importlib_metadata import distribution
+    except ImportError:
+        from pkg_resources import load_entry_point
+
+
+def importlib_load_entry_point(spec, group, name):
+    dist_name, _, _ = spec.partition('==')
+    matches = (
+        entry_point
+        for entry_point in distribution(dist_name).entry_points
+        if entry_point.group == group and entry_point.name == name
+    )
+    return next(matches).load()
+
+
+globals().setdefault('load_entry_point', importlib_load_entry_point)
+
+
+if __name__ == '__main__':
+    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
+    sys.exit(load_entry_point('sphero-mini-controller==0.0.0', 'console_scripts', 'test_node')())
diff --git a/ros2_ws/install/sphero_mini_controller/share/ament_index/resource_index/packages/sphero_mini_controller b/ros2_ws/install/sphero_mini_controller/share/ament_index/resource_index/packages/sphero_mini_controller
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/install/sphero_mini_controller/share/colcon-core/packages/sphero_mini_controller b/ros2_ws/install/sphero_mini_controller/share/colcon-core/packages/sphero_mini_controller
new file mode 100644
index 0000000..4fb1cbf
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/colcon-core/packages/sphero_mini_controller
@@ -0,0 +1 @@
+_constants:bluepy:bluepy.btle:box:cv2:geometry_msgs.msg:matplotlib.pyplot:numpy:queue:rclpy:sensor_msgs.msg:struct:sys:threading:time:treiber
\ No newline at end of file
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.dsv b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.dsv
new file mode 100644
index 0000000..79d4c95
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate;AMENT_PREFIX_PATH;
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.ps1 b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.ps1
new file mode 100644
index 0000000..26b9997
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.ps1
@@ -0,0 +1,3 @@
+# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em
+
+colcon_prepend_unique_value AMENT_PREFIX_PATH "$env:COLCON_CURRENT_PREFIX"
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.sh b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.sh
new file mode 100644
index 0000000..f3041f6
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.sh
@@ -0,0 +1,3 @@
+# generated from colcon_core/shell/template/hook_prepend_value.sh.em
+
+_colcon_prepend_unique_value AMENT_PREFIX_PATH "$COLCON_CURRENT_PREFIX"
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.dsv b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.dsv
new file mode 100644
index 0000000..257067d
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate;PYTHONPATH;lib/python3.10/site-packages
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.ps1 b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.ps1
new file mode 100644
index 0000000..caffe83
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.ps1
@@ -0,0 +1,3 @@
+# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em
+
+colcon_prepend_unique_value PYTHONPATH "$env:COLCON_CURRENT_PREFIX\lib/python3.10/site-packages"
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.sh b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.sh
new file mode 100644
index 0000000..660c348
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.sh
@@ -0,0 +1,3 @@
+# generated from colcon_core/shell/template/hook_prepend_value.sh.em
+
+_colcon_prepend_unique_value PYTHONPATH "$COLCON_CURRENT_PREFIX/lib/python3.10/site-packages"
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.bash b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.bash
new file mode 100644
index 0000000..ba62e9b
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.bash
@@ -0,0 +1,31 @@
+# generated from colcon_bash/shell/template/package.bash.em
+
+# This script extends the environment for this package.
+
+# a bash script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  # the prefix is two levels up from the package specific share directory
+  _colcon_package_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`/../.." > /dev/null && pwd)"
+else
+  _colcon_package_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+_colcon_package_bash_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo ". \"$1\""
+    fi
+    . "$@"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# source sh script of this package
+_colcon_package_bash_source_script "$_colcon_package_bash_COLCON_CURRENT_PREFIX/share/sphero_mini_controller/package.sh"
+
+unset _colcon_package_bash_source_script
+unset _colcon_package_bash_COLCON_CURRENT_PREFIX
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.dsv b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.dsv
new file mode 100644
index 0000000..2e5c1c2
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.dsv
@@ -0,0 +1,6 @@
+source;share/sphero_mini_controller/hook/pythonpath.ps1
+source;share/sphero_mini_controller/hook/pythonpath.dsv
+source;share/sphero_mini_controller/hook/pythonpath.sh
+source;share/sphero_mini_controller/hook/ament_prefix_path.ps1
+source;share/sphero_mini_controller/hook/ament_prefix_path.dsv
+source;share/sphero_mini_controller/hook/ament_prefix_path.sh
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.ps1 b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.ps1
new file mode 100644
index 0000000..66a433e
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.ps1
@@ -0,0 +1,116 @@
+# generated from colcon_powershell/shell/template/package.ps1.em
+
+# function to append a value to a variable
+# which uses colons as separators
+# duplicates as well as leading separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+function colcon_append_unique_value {
+  param (
+    $_listname,
+    $_value
+  )
+
+  # get values from variable
+  if (Test-Path Env:$_listname) {
+    $_values=(Get-Item env:$_listname).Value
+  } else {
+    $_values=""
+  }
+  $_duplicate=""
+  # start with no values
+  $_all_values=""
+  # iterate over existing values in the variable
+  if ($_values) {
+    $_values.Split(";") | ForEach {
+      # not an empty string
+      if ($_) {
+        # not a duplicate of _value
+        if ($_ -eq $_value) {
+          $_duplicate="1"
+        }
+        if ($_all_values) {
+          $_all_values="${_all_values};$_"
+        } else {
+          $_all_values="$_"
+        }
+      }
+    }
+  }
+  # append only non-duplicates
+  if (!$_duplicate) {
+    # avoid leading separator
+    if ($_all_values) {
+      $_all_values="${_all_values};${_value}"
+    } else {
+      $_all_values="${_value}"
+    }
+  }
+
+  # export the updated variable
+  Set-Item env:\$_listname -Value "$_all_values"
+}
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+function colcon_prepend_unique_value {
+  param (
+    $_listname,
+    $_value
+  )
+
+  # get values from variable
+  if (Test-Path Env:$_listname) {
+    $_values=(Get-Item env:$_listname).Value
+  } else {
+    $_values=""
+  }
+  # start with the new value
+  $_all_values="$_value"
+  # iterate over existing values in the variable
+  if ($_values) {
+    $_values.Split(";") | ForEach {
+      # not an empty string
+      if ($_) {
+        # not a duplicate of _value
+        if ($_ -ne $_value) {
+          # keep non-duplicate values
+          $_all_values="${_all_values};$_"
+        }
+      }
+    }
+  }
+  # export the updated variable
+  Set-Item env:\$_listname -Value "$_all_values"
+}
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+function colcon_package_source_powershell_script {
+  param (
+    $_colcon_package_source_powershell_script
+  )
+  # source script with conditional trace output
+  if (Test-Path $_colcon_package_source_powershell_script) {
+    if ($env:COLCON_TRACE) {
+      echo ". '$_colcon_package_source_powershell_script'"
+    }
+    . "$_colcon_package_source_powershell_script"
+  } else {
+    Write-Error "not found: '$_colcon_package_source_powershell_script'"
+  }
+}
+
+
+# a powershell script is able to determine its own path
+# the prefix is two levels up from the package specific share directory
+$env:COLCON_CURRENT_PREFIX=(Get-Item $PSCommandPath).Directory.Parent.Parent.FullName
+
+colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\share/sphero_mini_controller/hook/pythonpath.ps1"
+colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\share/sphero_mini_controller/hook/ament_prefix_path.ps1"
+
+Remove-Item Env:\COLCON_CURRENT_PREFIX
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.sh b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.sh
new file mode 100644
index 0000000..ccf55cf
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.sh
@@ -0,0 +1,87 @@
+# generated from colcon_core/shell/template/package.sh.em
+
+# This script extends the environment for this package.
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prepend_unique_value() {
+  # arguments
+  _listname="$1"
+  _value="$2"
+
+  # get values from variable
+  eval _values=\"\$$_listname\"
+  # backup the field separator
+  _colcon_prepend_unique_value_IFS=$IFS
+  IFS=":"
+  # start with the new value
+  _all_values="$_value"
+  # workaround SH_WORD_SPLIT not being set in zsh
+  if [ "$(command -v colcon_zsh_convert_to_array)" ]; then
+    colcon_zsh_convert_to_array _values
+  fi
+  # iterate over existing values in the variable
+  for _item in $_values; do
+    # ignore empty strings
+    if [ -z "$_item" ]; then
+      continue
+    fi
+    # ignore duplicates of _value
+    if [ "$_item" = "$_value" ]; then
+      continue
+    fi
+    # keep non-duplicate values
+    _all_values="$_all_values:$_item"
+  done
+  unset _item
+  # restore the field separator
+  IFS=$_colcon_prepend_unique_value_IFS
+  unset _colcon_prepend_unique_value_IFS
+  # export the updated variable
+  eval export $_listname=\"$_all_values\"
+  unset _all_values
+  unset _values
+
+  unset _value
+  unset _listname
+}
+
+# since a plain shell script can't determine its own path when being sourced
+# either use the provided COLCON_CURRENT_PREFIX
+# or fall back to the build time prefix (if it exists)
+_colcon_package_sh_COLCON_CURRENT_PREFIX="/home/ubuntu/ros2_ws/install/sphero_mini_controller"
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  if [ ! -d "$_colcon_package_sh_COLCON_CURRENT_PREFIX" ]; then
+    echo "The build time path \"$_colcon_package_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2
+    unset _colcon_package_sh_COLCON_CURRENT_PREFIX
+    return 1
+  fi
+  COLCON_CURRENT_PREFIX="$_colcon_package_sh_COLCON_CURRENT_PREFIX"
+fi
+unset _colcon_package_sh_COLCON_CURRENT_PREFIX
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+_colcon_package_sh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$@"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# source sh hooks
+_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/sphero_mini_controller/hook/pythonpath.sh"
+_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/sphero_mini_controller/hook/ament_prefix_path.sh"
+
+unset _colcon_package_sh_source_script
+unset COLCON_CURRENT_PREFIX
+
+# do not unset _colcon_prepend_unique_value since it might be used by non-primary shell hooks
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.xml b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.xml
new file mode 100644
index 0000000..abe0e77
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
+<package format="3">
+  <name>sphero_mini_controller</name>
+  <version>0.0.0</version>
+  <description>TODO: Package description</description>
+  <maintainer email="ubuntu@todo.todo">ubuntu</maintainer>
+  <license>TODO: License declaration</license>
+
+  <depend>rclpy</depend>
+  <depend>sensor_msgs.msg</depend>
+  <depend>geometry_msgs.msg</depend>
+  <depend>box</depend>
+  <depend>numpy</depend>
+  <depend>treiber</depend>
+  <depend>bluepy.btle</depend>
+  <depend>bluepy</depend>
+  <depend>_constants</depend>
+  <depend>struct</depend>
+  <depend>time</depend>
+  <depend>sys</depend>
+  <depend>threading</depend>
+  <depend>cv2</depend> 
+  <depend>queue</depend>
+  <depend>matplotlib.pyplot</depend>
+
+  <test_depend>ament_copyright</test_depend>
+  <test_depend>ament_flake8</test_depend>
+  <test_depend>ament_pep257</test_depend>
+  <test_depend>python3-pytest</test_depend>
+
+  <export>
+    <build_type>ament_python</build_type>
+  </export>
+</package>
diff --git a/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.zsh b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.zsh
new file mode 100644
index 0000000..4229ad7
--- /dev/null
+++ b/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.zsh
@@ -0,0 +1,42 @@
+# generated from colcon_zsh/shell/template/package.zsh.em
+
+# This script extends the environment for this package.
+
+# a zsh script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  # the prefix is two levels up from the package specific share directory
+  _colcon_package_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`/../.." > /dev/null && pwd)"
+else
+  _colcon_package_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+_colcon_package_zsh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo ". \"$1\""
+    fi
+    . "$@"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# function to convert array-like strings into arrays
+# to workaround SH_WORD_SPLIT not being set
+colcon_zsh_convert_to_array() {
+  local _listname=$1
+  local _dollar="$"
+  local _split="{="
+  local _to_array="(\"$_dollar$_split$_listname}\")"
+  eval $_listname=$_to_array
+}
+
+# source sh script of this package
+_colcon_package_zsh_source_script "$_colcon_package_zsh_COLCON_CURRENT_PREFIX/share/sphero_mini_controller/package.sh"
+unset convert_zsh_to_array
+
+unset _colcon_package_zsh_source_script
+unset _colcon_package_zsh_COLCON_CURRENT_PREFIX
diff --git a/ros2_ws/log/COLCON_IGNORE b/ros2_ws/log/COLCON_IGNORE
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/log/build_2023-07-05_16-11-36/events.log b/ros2_ws/log/build_2023-07-05_16-11-36/events.log
new file mode 100644
index 0000000..b51af15
--- /dev/null
+++ b/ros2_ws/log/build_2023-07-05_16-11-36/events.log
@@ -0,0 +1,38 @@
+[0.000000] (-) TimerEvent: {}
+[0.000094] (sphero_mini_controller) JobQueued: {'identifier': 'sphero_mini_controller', 'dependencies': OrderedDict()}
+[0.000145] (sphero_mini_controller) JobStarted: {'identifier': 'sphero_mini_controller'}
+[0.098612] (-) TimerEvent: {}
+[0.198900] (-) TimerEvent: {}
+[0.299181] (-) TimerEvent: {}
+[0.399461] (-) TimerEvent: {}
+[0.499733] (-) TimerEvent: {}
+[0.600065] (-) TimerEvent: {}
+[0.613340] (sphero_mini_controller) Command: {'cmd': ['/usr/bin/python3', 'setup.py', 'egg_info', '--egg-base', '../../build/sphero_mini_controller', 'build', '--build-base', '/home/ubuntu/ros2_ws/build/sphero_mini_controller/build', 'install', '--record', '/home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log', '--single-version-externally-managed'], 'cwd': '/home/ubuntu/ros2_ws/src/sphero_mini_controller', 'env': {'LANGUAGE': 'de_DE:en', 'USER': 'ubuntu', 'LC_TIME': 'de_DE.UTF-8', 'XDG_SESSION_TYPE': 'x11', 'SHLVL': '1', 'LD_LIBRARY_PATH': '/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/x86_64-linux-gnu:/opt/ros/humble/lib', 'HOME': '/home/ubuntu', 'OLDPWD': '/home/ubuntu', 'DESKTOP_SESSION': 'ubuntu', 'ROS_PYTHON_VERSION': '3', 'GNOME_SHELL_SESSION_MODE': 'ubuntu', 'GTK_MODULES': 'gail:atk-bridge', 'LC_MONETARY': 'de_DE.UTF-8', 'SYSTEMD_EXEC_PID': '2511', 'DBUS_SESSION_BUS_ADDRESS': 'unix:path=/run/user/999/bus', 'COLORTERM': 'truecolor', 'IM_CONFIG_PHASE': '1', 'ROS_DISTRO': 'humble', 'LOGNAME': 'ubuntu', '_': '/usr/bin/colcon', 'ROS_VERSION': '2', 'XDG_SESSION_CLASS': 'user', 'USERNAME': 'ubuntu', 'TERM': 'xterm-256color', 'GNOME_DESKTOP_SESSION_ID': 'this-is-deprecated', 'ROS_LOCALHOST_ONLY': '0', 'WINDOWPATH': '2', 'PATH': '/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin', 'SESSION_MANAGER': 'local/ubuntu:@/tmp/.ICE-unix/2486,unix/ubuntu:/tmp/.ICE-unix/2486', 'PAPERSIZE': 'a4', 'XDG_MENU_PREFIX': 'gnome-', 'LC_ADDRESS': 'de_DE.UTF-8', 'GNOME_TERMINAL_SCREEN': '/org/gnome/Terminal/screen/e134bf1a_3465_43a9_88f4_21d27316a303', 'XDG_RUNTIME_DIR': '/run/user/999', 'DISPLAY': ':0', 'LANG': 'de_DE.UTF-8', 'XDG_CURRENT_DESKTOP': 'ubuntu:GNOME', 'LC_TELEPHONE': 'de_DE.UTF-8', 'XMODIFIERS': '@im=ibus', 'XDG_SESSION_DESKTOP': 'ubuntu', 'XAUTHORITY': '/run/user/999/gdm/Xauthority', 'GNOME_TERMINAL_SERVICE': ':1.129', 'SSH_AGENT_LAUNCHER': 'gnome-keyring', 'SSH_AUTH_SOCK': '/run/user/999/keyring/ssh', 'AMENT_PREFIX_PATH': '/opt/ros/humble', 'SHELL': '/bin/bash', 'LC_NAME': 'de_DE.UTF-8', 'QT_ACCESSIBILITY': '1', 'GDMSESSION': 'ubuntu', 'WEBOTS_HOME': '/usr/local/webots', 'LC_MEASUREMENT': 'de_DE.UTF-8', 'GPG_AGENT_INFO': '/run/user/999/gnupg/S.gpg-agent:0:1', 'LC_IDENTIFICATION': 'de_DE.UTF-8', 'QT_IM_MODULE': 'ibus', 'PWD': '/home/ubuntu/ros2_ws/build/sphero_mini_controller', 'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/etc/xdg', 'XDG_DATA_DIRS': '/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop', 'PYTHONPATH': '/home/ubuntu/ros2_ws/build/sphero_mini_controller/prefix_override:/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages:/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages', 'LC_NUMERIC': 'de_DE.UTF-8', 'LC_PAPER': 'de_DE.UTF-8', 'COLCON': '1', 'VTE_VERSION': '6800'}, 'shell': False}
+[0.700191] (-) TimerEvent: {}
+[0.800481] (-) TimerEvent: {}
+[0.837582] (sphero_mini_controller) StdoutLine: {'line': b'running egg_info\n'}
+[0.838134] (sphero_mini_controller) StdoutLine: {'line': b'writing ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO\n'}
+[0.838269] (sphero_mini_controller) StdoutLine: {'line': b'writing dependency_links to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt\n'}
+[0.838506] (sphero_mini_controller) StdoutLine: {'line': b'writing entry points to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt\n'}
+[0.838674] (sphero_mini_controller) StdoutLine: {'line': b'writing requirements to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt\n'}
+[0.838808] (sphero_mini_controller) StdoutLine: {'line': b'writing top-level names to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt\n'}
+[0.840404] (sphero_mini_controller) StdoutLine: {'line': b"reading manifest file '../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt'\n"}
+[0.841553] (sphero_mini_controller) StdoutLine: {'line': b"writing manifest file '../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt'\n"}
+[0.841722] (sphero_mini_controller) StdoutLine: {'line': b'running build\n'}
+[0.841821] (sphero_mini_controller) StdoutLine: {'line': b'running build_py\n'}
+[0.842619] (sphero_mini_controller) StdoutLine: {'line': b'copying sphero_mini_controller/my_first_node.py -> /home/ubuntu/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller\n'}
+[0.843943] (sphero_mini_controller) StdoutLine: {'line': b'running install\n'}
+[0.844204] (sphero_mini_controller) StdoutLine: {'line': b'running install_lib\n'}
+[0.844828] (sphero_mini_controller) StdoutLine: {'line': b'copying /home/ubuntu/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node.py -> /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller\n'}
+[0.846179] (sphero_mini_controller) StdoutLine: {'line': b'byte-compiling /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py to my_first_node.cpython-310.pyc\n'}
+[0.850045] (sphero_mini_controller) StdoutLine: {'line': b'running install_data\n'}
+[0.851406] (sphero_mini_controller) StdoutLine: {'line': b'running install_egg_info\n'}
+[0.852604] (sphero_mini_controller) StdoutLine: {'line': b"removing '/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info' (and everything under it)\n"}
+[0.852894] (sphero_mini_controller) StdoutLine: {'line': b'Copying ../../build/sphero_mini_controller/sphero_mini_controller.egg-info to /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info\n'}
+[0.853897] (sphero_mini_controller) StdoutLine: {'line': b'running install_scripts\n'}
+[0.869686] (sphero_mini_controller) StdoutLine: {'line': b'Installing sphero_mini script to /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller\n'}
+[0.870533] (sphero_mini_controller) StdoutLine: {'line': b"writing list of installed files to '/home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log'\n"}
+[0.894265] (sphero_mini_controller) CommandEnded: {'returncode': 0}
+[0.900811] (-) TimerEvent: {}
+[0.911226] (sphero_mini_controller) JobEnded: {'identifier': 'sphero_mini_controller', 'rc': 0}
+[0.911779] (-) EventReactorShutdown: {}
diff --git a/ros2_ws/log/build_2023-07-05_16-11-36/logger_all.log b/ros2_ws/log/build_2023-07-05_16-11-36/logger_all.log
new file mode 100644
index 0000000..79ba79d
--- /dev/null
+++ b/ros2_ws/log/build_2023-07-05_16-11-36/logger_all.log
@@ -0,0 +1,126 @@
+[0.285s] DEBUG:colcon:Command line arguments: ['/usr/bin/colcon', 'build']
+[0.285s] DEBUG:colcon:Parsed command line arguments: Namespace(log_base=None, log_level=None, verb_name='build', build_base='build', install_base='install', merge_install=False, symlink_install=False, test_result_base=None, continue_on_error=False, executor='parallel', parallel_workers=8, event_handlers=None, ignore_user_meta=False, metas=['./colcon.meta'], base_paths=['.'], packages_ignore=None, packages_ignore_regex=None, paths=None, packages_up_to=None, packages_up_to_regex=None, packages_above=None, packages_above_and_dependencies=None, packages_above_depth=None, packages_select_by_dep=None, packages_skip_by_dep=None, packages_skip_up_to=None, packages_select_build_failed=False, packages_skip_build_finished=False, packages_select_test_failures=False, packages_skip_test_passed=False, packages_select=None, packages_skip=None, packages_select_regex=None, packages_skip_regex=None, packages_start=None, packages_end=None, allow_overriding=[], cmake_args=None, cmake_target=None, cmake_target_skip_unavailable=False, cmake_clean_cache=False, cmake_clean_first=False, cmake_force_configure=False, ament_cmake_args=None, catkin_cmake_args=None, catkin_skip_building_tests=False, verb_parser=<colcon_defaults.argument_parser.defaults.DefaultArgumentsDecorator object at 0x7f34ebc57490>, verb_extension=<colcon_core.verb.build.BuildVerb object at 0x7f34ebc56f20>, main=<bound method BuildVerb.main of <colcon_core.verb.build.BuildVerb object at 0x7f34ebc56f20>>)
+[0.322s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) check parameters
+[0.322s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) check parameters
+[0.322s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) check parameters
+[0.322s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) check parameters
+[0.322s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) discover
+[0.322s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) discover
+[0.322s] INFO:colcon.colcon_core.package_discovery:Crawling recursively for packages in '/home/ubuntu/ros2_ws'
+[0.322s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ignore', 'ignore_ament_install']
+[0.322s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore'
+[0.322s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore_ament_install'
+[0.322s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_pkg']
+[0.322s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_pkg'
+[0.322s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_meta']
+[0.322s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_meta'
+[0.323s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ros']
+[0.323s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ros'
+[0.332s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['cmake', 'python']
+[0.332s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'cmake'
+[0.332s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python'
+[0.332s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['python_setup_py']
+[0.332s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python_setup_py'
+[0.332s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extensions ['ignore', 'ignore_ament_install']
+[0.332s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extension 'ignore'
+[0.332s] Level 1:colcon.colcon_core.package_identification:_identify(build) ignored
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extensions ['ignore', 'ignore_ament_install']
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extension 'ignore'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(install) ignored
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extensions ['ignore', 'ignore_ament_install']
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extension 'ignore'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(log) ignored
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ignore', 'ignore_ament_install']
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore_ament_install'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_pkg']
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_pkg'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_meta']
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_meta'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ros']
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ros'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['cmake', 'python']
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'cmake'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['python_setup_py']
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python_setup_py'
+[0.333s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extensions ['ignore', 'ignore_ament_install']
+[0.334s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extension 'ignore'
+[0.334s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extension 'ignore_ament_install'
+[0.334s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extensions ['colcon_pkg']
+[0.334s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extension 'colcon_pkg'
+[0.334s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extensions ['colcon_meta']
+[0.334s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extension 'colcon_meta'
+[0.334s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extensions ['ros']
+[0.334s] Level 1:colcon.colcon_core.package_identification:_identify(src/sphero_mini_controller) by extension 'ros'
+[0.338s] DEBUG:colcon.colcon_core.package_identification:Package 'src/sphero_mini_controller' with type 'ros.ament_python' and name 'sphero_mini_controller'
+[0.338s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) using defaults
+[0.338s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) discover
+[0.338s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) using defaults
+[0.338s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) discover
+[0.338s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) using defaults
+[0.359s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) check parameters
+[0.359s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) discover
+[0.364s] DEBUG:colcon.colcon_installed_package_information.package_discovery:Found 302 installed packages in /opt/ros/humble
+[0.365s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) using defaults
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'cmake_args' from command line to 'None'
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'cmake_target' from command line to 'None'
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'cmake_target_skip_unavailable' from command line to 'False'
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'cmake_clean_cache' from command line to 'False'
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'cmake_clean_first' from command line to 'False'
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'cmake_force_configure' from command line to 'False'
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'ament_cmake_args' from command line to 'None'
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'catkin_cmake_args' from command line to 'None'
+[0.418s] Level 5:colcon.colcon_core.verb:set package 'sphero_mini_controller' build argument 'catkin_skip_building_tests' from command line to 'False'
+[0.418s] DEBUG:colcon.colcon_core.verb:Building package 'sphero_mini_controller' with the following arguments: {'ament_cmake_args': None, 'build_base': '/home/ubuntu/ros2_ws/build/sphero_mini_controller', 'catkin_cmake_args': None, 'catkin_skip_building_tests': False, 'cmake_args': None, 'cmake_clean_cache': False, 'cmake_clean_first': False, 'cmake_force_configure': False, 'cmake_target': None, 'cmake_target_skip_unavailable': False, 'install_base': '/home/ubuntu/ros2_ws/install/sphero_mini_controller', 'merge_install': False, 'path': '/home/ubuntu/ros2_ws/src/sphero_mini_controller', 'symlink_install': False, 'test_result_base': None}
+[0.419s] INFO:colcon.colcon_core.executor:Executing jobs using 'parallel' executor
+[0.421s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete
+[0.421s] INFO:colcon.colcon_ros.task.ament_python.build:Building ROS package in '/home/ubuntu/ros2_ws/src/sphero_mini_controller' with build type 'ament_python'
+[0.421s] Level 1:colcon.colcon_core.shell:create_environment_hook('sphero_mini_controller', 'ament_prefix_path')
+[0.427s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_core.shell.bat': Not used on non-Windows systems
+[0.427s] INFO:colcon.colcon_core.shell:Creating environment hook '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.ps1'
+[0.428s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.dsv'
+[0.429s] INFO:colcon.colcon_core.shell:Creating environment hook '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/ament_prefix_path.sh'
+[0.431s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell
+[0.431s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment
+[0.671s] INFO:colcon.colcon_core.task.python.build:Building Python package in '/home/ubuntu/ros2_ws/src/sphero_mini_controller'
+[0.672s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell
+[0.672s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment
+[1.036s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoking command in '/home/ubuntu/ros2_ws/src/sphero_mini_controller': PYTHONPATH=/home/ubuntu/ros2_ws/build/sphero_mini_controller/prefix_override:/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 setup.py egg_info --egg-base ../../build/sphero_mini_controller build --build-base /home/ubuntu/ros2_ws/build/sphero_mini_controller/build install --record /home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log --single-version-externally-managed
+[1.317s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoked command in '/home/ubuntu/ros2_ws/src/sphero_mini_controller' returned '0': PYTHONPATH=/home/ubuntu/ros2_ws/build/sphero_mini_controller/prefix_override:/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 setup.py egg_info --egg-base ../../build/sphero_mini_controller build --build-base /home/ubuntu/ros2_ws/build/sphero_mini_controller/build install --record /home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log --single-version-externally-managed
+[1.323s] Level 1:colcon.colcon_core.environment:checking '/home/ubuntu/ros2_ws/install/sphero_mini_controller' for CMake module files
+[1.324s] Level 1:colcon.colcon_core.environment:checking '/home/ubuntu/ros2_ws/install/sphero_mini_controller' for CMake config files
+[1.325s] Level 1:colcon.colcon_core.environment:checking '/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib'
+[1.325s] Level 1:colcon.colcon_core.environment:checking '/home/ubuntu/ros2_ws/install/sphero_mini_controller/bin'
+[1.325s] Level 1:colcon.colcon_core.environment:checking '/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/pkgconfig/sphero_mini_controller.pc'
+[1.325s] Level 1:colcon.colcon_core.environment:checking '/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages'
+[1.325s] Level 1:colcon.colcon_core.shell:create_environment_hook('sphero_mini_controller', 'pythonpath')
+[1.327s] INFO:colcon.colcon_core.shell:Creating environment hook '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.ps1'
+[1.327s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.dsv'
+[1.327s] INFO:colcon.colcon_core.shell:Creating environment hook '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/hook/pythonpath.sh'
+[1.328s] Level 1:colcon.colcon_core.environment:checking '/home/ubuntu/ros2_ws/install/sphero_mini_controller/bin'
+[1.328s] Level 1:colcon.colcon_core.environment:create_environment_scripts_only(sphero_mini_controller)
+[1.329s] INFO:colcon.colcon_core.shell:Creating package script '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.ps1'
+[1.330s] INFO:colcon.colcon_core.shell:Creating package descriptor '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.dsv'
+[1.331s] INFO:colcon.colcon_core.shell:Creating package script '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.sh'
+[1.331s] INFO:colcon.colcon_core.shell:Creating package script '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.bash'
+[1.332s] INFO:colcon.colcon_core.shell:Creating package script '/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/sphero_mini_controller/package.zsh'
+[1.333s] Level 1:colcon.colcon_core.environment:create_file_with_runtime_dependencies(/home/ubuntu/ros2_ws/install/sphero_mini_controller/share/colcon-core/packages/sphero_mini_controller)
+[1.333s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:closing loop
+[1.334s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:loop closed
+[1.334s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete finished with '0'
+[1.334s] DEBUG:colcon.colcon_core.event_reactor:joining thread
+[1.341s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.terminal_notifier': Not used on non-Darwin systems
+[1.341s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.win32': Not used on non-Windows systems
+[1.341s] INFO:colcon.colcon_notification.desktop_notification:Sending desktop notification using 'notify2'
+[1.356s] DEBUG:colcon.colcon_core.event_reactor:joined thread
+[1.358s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/ubuntu/ros2_ws/install/local_setup.ps1'
+[1.359s] INFO:colcon.colcon_core.shell:Creating prefix util module '/home/ubuntu/ros2_ws/install/_local_setup_util_ps1.py'
+[1.361s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/ubuntu/ros2_ws/install/setup.ps1'
+[1.362s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/ubuntu/ros2_ws/install/local_setup.sh'
+[1.363s] INFO:colcon.colcon_core.shell:Creating prefix util module '/home/ubuntu/ros2_ws/install/_local_setup_util_sh.py'
+[1.363s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/ubuntu/ros2_ws/install/setup.sh'
+[1.365s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/ubuntu/ros2_ws/install/local_setup.bash'
+[1.366s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/ubuntu/ros2_ws/install/setup.bash'
+[1.367s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/ubuntu/ros2_ws/install/local_setup.zsh'
+[1.368s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/ubuntu/ros2_ws/install/setup.zsh'
diff --git a/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/command.log b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/command.log
new file mode 100644
index 0000000..4f3d645
--- /dev/null
+++ b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/command.log
@@ -0,0 +1,2 @@
+Invoking command in '/home/ubuntu/ros2_ws/src/sphero_mini_controller': PYTHONPATH=/home/ubuntu/ros2_ws/build/sphero_mini_controller/prefix_override:/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 setup.py egg_info --egg-base ../../build/sphero_mini_controller build --build-base /home/ubuntu/ros2_ws/build/sphero_mini_controller/build install --record /home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log --single-version-externally-managed
+Invoked command in '/home/ubuntu/ros2_ws/src/sphero_mini_controller' returned '0': PYTHONPATH=/home/ubuntu/ros2_ws/build/sphero_mini_controller/prefix_override:/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 setup.py egg_info --egg-base ../../build/sphero_mini_controller build --build-base /home/ubuntu/ros2_ws/build/sphero_mini_controller/build install --record /home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log --single-version-externally-managed
diff --git a/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stderr.log b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stderr.log
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stdout.log b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stdout.log
new file mode 100644
index 0000000..e0f7d75
--- /dev/null
+++ b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stdout.log
@@ -0,0 +1,22 @@
+running egg_info
+writing ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO
+writing dependency_links to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt
+writing entry points to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt
+writing requirements to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt
+writing top-level names to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt
+reading manifest file '../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt'
+writing manifest file '../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt'
+running build
+running build_py
+copying sphero_mini_controller/my_first_node.py -> /home/ubuntu/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller
+running install
+running install_lib
+copying /home/ubuntu/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node.py -> /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller
+byte-compiling /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py to my_first_node.cpython-310.pyc
+running install_data
+running install_egg_info
+removing '/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info' (and everything under it)
+Copying ../../build/sphero_mini_controller/sphero_mini_controller.egg-info to /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info
+running install_scripts
+Installing sphero_mini script to /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller
+writing list of installed files to '/home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log'
diff --git a/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stdout_stderr.log b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stdout_stderr.log
new file mode 100644
index 0000000..e0f7d75
--- /dev/null
+++ b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/stdout_stderr.log
@@ -0,0 +1,22 @@
+running egg_info
+writing ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO
+writing dependency_links to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt
+writing entry points to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt
+writing requirements to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt
+writing top-level names to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt
+reading manifest file '../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt'
+writing manifest file '../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt'
+running build
+running build_py
+copying sphero_mini_controller/my_first_node.py -> /home/ubuntu/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller
+running install
+running install_lib
+copying /home/ubuntu/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node.py -> /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller
+byte-compiling /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py to my_first_node.cpython-310.pyc
+running install_data
+running install_egg_info
+removing '/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info' (and everything under it)
+Copying ../../build/sphero_mini_controller/sphero_mini_controller.egg-info to /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info
+running install_scripts
+Installing sphero_mini script to /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller
+writing list of installed files to '/home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log'
diff --git a/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/streams.log b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/streams.log
new file mode 100644
index 0000000..c3cd893
--- /dev/null
+++ b/ros2_ws/log/build_2023-07-05_16-11-36/sphero_mini_controller/streams.log
@@ -0,0 +1,24 @@
+[0.614s] Invoking command in '/home/ubuntu/ros2_ws/src/sphero_mini_controller': PYTHONPATH=/home/ubuntu/ros2_ws/build/sphero_mini_controller/prefix_override:/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 setup.py egg_info --egg-base ../../build/sphero_mini_controller build --build-base /home/ubuntu/ros2_ws/build/sphero_mini_controller/build install --record /home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log --single-version-externally-managed
+[0.838s] running egg_info
+[0.838s] writing ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/PKG-INFO
+[0.838s] writing dependency_links to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/dependency_links.txt
+[0.838s] writing entry points to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/entry_points.txt
+[0.839s] writing requirements to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/requires.txt
+[0.839s] writing top-level names to ../../build/sphero_mini_controller/sphero_mini_controller.egg-info/top_level.txt
+[0.840s] reading manifest file '../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt'
+[0.841s] writing manifest file '../../build/sphero_mini_controller/sphero_mini_controller.egg-info/SOURCES.txt'
+[0.842s] running build
+[0.842s] running build_py
+[0.843s] copying sphero_mini_controller/my_first_node.py -> /home/ubuntu/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller
+[0.844s] running install
+[0.844s] running install_lib
+[0.845s] copying /home/ubuntu/ros2_ws/build/sphero_mini_controller/build/lib/sphero_mini_controller/my_first_node.py -> /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller
+[0.846s] byte-compiling /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller/my_first_node.py to my_first_node.cpython-310.pyc
+[0.850s] running install_data
+[0.851s] running install_egg_info
+[0.853s] removing '/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info' (and everything under it)
+[0.853s] Copying ../../build/sphero_mini_controller/sphero_mini_controller.egg-info to /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages/sphero_mini_controller-0.0.0-py3.10.egg-info
+[0.854s] running install_scripts
+[0.870s] Installing sphero_mini script to /home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/sphero_mini_controller
+[0.870s] writing list of installed files to '/home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log'
+[0.894s] Invoked command in '/home/ubuntu/ros2_ws/src/sphero_mini_controller' returned '0': PYTHONPATH=/home/ubuntu/ros2_ws/build/sphero_mini_controller/prefix_override:/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 setup.py egg_info --egg-base ../../build/sphero_mini_controller build --build-base /home/ubuntu/ros2_ws/build/sphero_mini_controller/build install --record /home/ubuntu/ros2_ws/build/sphero_mini_controller/install.log --single-version-externally-managed
diff --git a/ros2_ws/log/latest b/ros2_ws/log/latest
new file mode 100644
index 0000000000000000000000000000000000000000..3244609549432b76ee2b151871ad47cc1e1f0f2d
GIT binary patch
literal 32
ncmeawE2;4D^JdIpNMtBsNM$HyC}D_aNMa~u$YjW2NMQf~iwOsY

literal 0
HcmV?d00001

diff --git a/ros2_ws/log/latest_build b/ros2_ws/log/latest_build
new file mode 100644
index 0000000000000000000000000000000000000000..ca67e1aa835f2f7f207f34c5b460777363f7af47
GIT binary patch
literal 58
zcmeawE2;4D^JYw9C}qfG$YDrfh-WZjFkmoZFlNwYFkmoe&}A@WFkpyhFkrA`&}A?M
Hi-1S~MpOvg

literal 0
HcmV?d00001

diff --git a/ros2_ws/src/sphero_mini_controller/.vscode/c_cpp_properties.json b/ros2_ws/src/sphero_mini_controller/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000..af5a8df
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/.vscode/c_cpp_properties.json
@@ -0,0 +1,20 @@
+{
+  "configurations": [
+    {
+      "browse": {
+        "databaseFilename": "${default}",
+        "limitSymbolsToIncludedHeaders": false
+      },
+      "includePath": [
+        "/opt/ros/humble/include/**",
+        "/usr/include/**"
+      ],
+      "name": "ROS",
+      "intelliSenseMode": "gcc-x64",
+      "compilerPath": "/usr/bin/gcc",
+      "cStandard": "gnu11",
+      "cppStandard": "c++14"
+    }
+  ],
+  "version": 4
+}
\ No newline at end of file
diff --git a/ros2_ws/src/sphero_mini_controller/.vscode/settings.json b/ros2_ws/src/sphero_mini_controller/.vscode/settings.json
new file mode 100644
index 0000000..2acdf0c
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/.vscode/settings.json
@@ -0,0 +1,13 @@
+{
+    "python.autoComplete.extraPaths": [
+        "/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages",
+        "/opt/ros/humble/lib/python3.10/site-packages",
+        "/opt/ros/humble/local/lib/python3.10/dist-packages"
+    ],
+    "python.analysis.extraPaths": [
+        "/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages",
+        "/opt/ros/humble/lib/python3.10/site-packages",
+        "/opt/ros/humble/local/lib/python3.10/dist-packages"
+    ],
+    "ros.distro": "humble"
+}
\ No newline at end of file
diff --git a/ros2_ws/src/sphero_mini_controller/package.xml b/ros2_ws/src/sphero_mini_controller/package.xml
new file mode 100644
index 0000000..abe0e77
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/package.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
+<package format="3">
+  <name>sphero_mini_controller</name>
+  <version>0.0.0</version>
+  <description>TODO: Package description</description>
+  <maintainer email="ubuntu@todo.todo">ubuntu</maintainer>
+  <license>TODO: License declaration</license>
+
+  <depend>rclpy</depend>
+  <depend>sensor_msgs.msg</depend>
+  <depend>geometry_msgs.msg</depend>
+  <depend>box</depend>
+  <depend>numpy</depend>
+  <depend>treiber</depend>
+  <depend>bluepy.btle</depend>
+  <depend>bluepy</depend>
+  <depend>_constants</depend>
+  <depend>struct</depend>
+  <depend>time</depend>
+  <depend>sys</depend>
+  <depend>threading</depend>
+  <depend>cv2</depend> 
+  <depend>queue</depend>
+  <depend>matplotlib.pyplot</depend>
+
+  <test_depend>ament_copyright</test_depend>
+  <test_depend>ament_flake8</test_depend>
+  <test_depend>ament_pep257</test_depend>
+  <test_depend>python3-pytest</test_depend>
+
+  <export>
+    <build_type>ament_python</build_type>
+  </export>
+</package>
diff --git a/ros2_ws/src/sphero_mini_controller/resource/sphero_conf.json b/ros2_ws/src/sphero_mini_controller/resource/sphero_conf.json
new file mode 100644
index 0000000..a490b4b
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/resource/sphero_conf.json
@@ -0,0 +1,3 @@
+{
+    "MAC_ADDRESS": "C6:69:72:CD:BC:6D"
+}
diff --git a/ros2_ws/src/sphero_mini_controller/resource/sphero_mini_controller b/ros2_ws/src/sphero_mini_controller/resource/sphero_mini_controller
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/src/sphero_mini_controller/setup.cfg b/ros2_ws/src/sphero_mini_controller/setup.cfg
new file mode 100644
index 0000000..54dced3
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/setup.cfg
@@ -0,0 +1,4 @@
+[develop]
+script_dir=$base/lib/sphero_mini_controller
+[install]
+install_scripts=$base/lib/sphero_mini_controller
diff --git a/ros2_ws/src/sphero_mini_controller/setup.py b/ros2_ws/src/sphero_mini_controller/setup.py
new file mode 100644
index 0000000..60d245a
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/setup.py
@@ -0,0 +1,27 @@
+from setuptools import setup
+
+package_name = 'sphero_mini_controller'
+
+setup(
+    name=package_name,
+    version='0.0.0',
+    packages=[package_name],
+    data_files=[
+        ('share/ament_index/resource_index/packages',
+            ['resource/' + package_name]),
+        ('share/' + package_name, ['package.xml']),
+    ],
+    install_requires=['setuptools'],
+    zip_safe=True,
+    maintainer='ubuntu',
+    maintainer_email='ubuntu@todo.todo',
+    description='TODO: Package description',
+    license='TODO: License declaration',
+    tests_require=['pytest'],
+    entry_points={
+        'console_scripts': [
+            "sphero_mini = sphero_mini_controller.sphero_mini:main"
+          
+        ],
+    },
+)
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/.vscode/c_cpp_properties.json b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000..af5a8df
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/.vscode/c_cpp_properties.json
@@ -0,0 +1,20 @@
+{
+  "configurations": [
+    {
+      "browse": {
+        "databaseFilename": "${default}",
+        "limitSymbolsToIncludedHeaders": false
+      },
+      "includePath": [
+        "/opt/ros/humble/include/**",
+        "/usr/include/**"
+      ],
+      "name": "ROS",
+      "intelliSenseMode": "gcc-x64",
+      "compilerPath": "/usr/bin/gcc",
+      "cStandard": "gnu11",
+      "cppStandard": "c++14"
+    }
+  ],
+  "version": 4
+}
\ No newline at end of file
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/.vscode/settings.json b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/.vscode/settings.json
new file mode 100644
index 0000000..c7c0d89
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/.vscode/settings.json
@@ -0,0 +1,12 @@
+{
+    "python.autoComplete.extraPaths": [
+        "/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages",
+        "/opt/ros/humble/lib/python3.10/site-packages",
+        "/opt/ros/humble/local/lib/python3.10/dist-packages"
+    ],
+    "python.analysis.extraPaths": [
+        "/home/ubuntu/ros2_ws/install/sphero_mini_controller/lib/python3.10/site-packages",
+        "/opt/ros/humble/lib/python3.10/site-packages",
+        "/opt/ros/humble/local/lib/python3.10/dist-packages"
+    ]
+}
\ No newline at end of file
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/WavefrontPlanner.py b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/WavefrontPlanner.py
new file mode 100644
index 0000000..9904dd9
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/WavefrontPlanner.py
@@ -0,0 +1,389 @@
+############################################################################
+# WAVEFRONT ALGORITHM
+# Adapted to Python Code By Darin Velarde
+# Fri Jan 29 13:56:53 PST 2010
+# from C code from John Palmisano 
+# (www.societyofrobots.com)
+############################################################################
+import cv2
+import numpy as np
+import matplotlib.pyplot as plt
+import time
+
+class waveFrontPlanner:
+    ############################################################################
+    # WAVEFRONT ALGORITHM
+    # Adapted to Python Code By Darin Velarde
+    # Fri Jan 29 13:56:53 PST 2010
+    # from C code from John Palmisano 
+    # (www.societyofrobots.com)
+    ############################################################################
+
+    def __init__(self, mapOfWorld, slow=False):
+        self.__slow = slow
+        self.__mapOfWorld = mapOfWorld
+        if str(type(mapOfWorld)).find("numpy") != -1:
+            #If its a numpy array
+            self.__height, self.__width = self.__mapOfWorld.shape
+        else:
+            self.__height, self.__width = len(self.__mapOfWorld), len(self.__mapOfWorld[0])
+
+        self.__nothing = 000
+        self.__wall = 999
+        self.__goal = 1
+        self.__path = "PATH"
+
+        self.__finalPath = []
+
+        #Robot value
+        self.__robot = 254
+        #Robot default Location
+        self.__robot_x = 0
+        self.__robot_y = 0
+
+        #default goal location
+        self.__goal_x = 8
+        self.__goal_y = 9
+
+        #temp variables
+        self.__temp_A = 0
+        self.__temp_B = 0
+        self.__counter = 0
+        self.__steps = 0 #determine how processor intensive the algorithm was
+
+        #when searching for a node with a lower value
+        self.__minimum_node = 250
+        self.__min_node_location = 250
+        self.__new_state = 1
+        self.__old_state = 1
+        self.__reset_min = 250 #above this number is a special (wall or robot)
+    ###########################################################################
+
+    def setRobotPosition(self, x, y):
+        """
+        Sets the robot's current position
+
+        """
+
+        self.__robot_x = x
+        self.__robot_y = y
+    ###########################################################################
+
+    def setGoalPosition(self, x, y):
+        """
+        Sets the goal position.
+
+        """
+
+        self.__goal_x = x
+        self.__goal_y = y
+    ###########################################################################
+
+    def robotPosition(self):
+        return  (self.__robot_x, self.__robot_y)
+    ###########################################################################
+
+    def goalPosition(self):
+        return  (self.__goal_x, self.__goal_y)
+    ###########################################################################
+
+    def run(self, prnt=False):
+        """
+        The entry point for the robot algorithm to use wavefront propagation.
+
+        """
+
+        path = []
+        while self.__mapOfWorld[self.__robot_x][self.__robot_y] != self.__goal:
+            if self.__steps > 20000:
+                print ("Cannot find a path.")
+                return
+            #find new location to go to
+            self.__new_state = self.propagateWavefront()
+            #update location of robot
+            if self.__new_state == 1:
+                self.__robot_x -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" % (self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 2:
+                self.__robot_y += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 3:
+                self.__robot_x += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 4:
+                self.__robot_y -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            self.__old_state = self.__new_state
+        msg = "Found the goal in %i steps:\n" % self.__steps
+        msg += "mapOfWorld size= %i %i\n\n" % (self.__height, self.__width)
+        if prnt:
+            print(msg)
+            self.printMap()
+        return path
+    ###########################################################################
+
+    def propagateWavefront(self, prnt=False):
+        self.unpropagate()
+        #Old robot location was deleted, store new robot location in mapOfWorld
+        self.__mapOfWorld[self.__robot_x][self.__robot_y] = self.__robot
+        self.__path = self.__robot
+        #start location to begin scan at goal location
+        self.__mapOfWorld[self.__goal_x][self.__goal_y] = self.__goal
+        counter = 0
+        while counter < 200:  #allows for recycling until robot is found
+            x = 0
+            y = 0
+            #time.sleep(0.00001)
+            #while the mapOfWorld hasnt been fully scanned
+            while x < self.__height and y < self.__width:
+                #if this location is a wall or the goal, just ignore it
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal:
+                    #a full trail to the robot has been located, finished!
+                    minLoc = self.minSurroundingNodeValue(x, y)
+                    if minLoc < self.__reset_min and \
+                        self.__mapOfWorld[x][y] == self.__robot:
+                        if prnt:
+                            print("Finished Wavefront:\n")
+                            self.printMap()
+                        # Tell the robot to move after this return.
+                        return self.__min_node_location
+                    #record a value in to this node
+                    elif self.__minimum_node != self.__reset_min:
+                        #if this isnt here, 'nothing' will go in the location
+                        self.__mapOfWorld[x][y] = self.__minimum_node + 1
+                #go to next node and/or row
+                y += 1
+                if y == self.__width and x != self.__height:
+                    x += 1
+                    y = 0
+            #print self.__robot_x, self.__robot_y
+            if prnt:
+                print("Sweep #: %i\n" % (counter + 1))
+                self.printMap()
+            self.__steps += 1
+            counter += 1
+        return 0
+    ###########################################################################
+
+    def unpropagate(self):
+        """
+        clears old path to determine new path
+        stay within boundary
+
+        """
+
+        for x in range(0, self.__height):
+            for y in range(0, self.__width):
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal and \
+                    self.__mapOfWorld[x][y] != self.__path:
+                    #if this location is a wall or goal, just ignore it
+                    self.__mapOfWorld[x][y] = self.__nothing #clear that space
+    ###########################################################################
+
+    def minSurroundingNodeValue(self, x, y):
+        """
+        this method looks at a node and returns the lowest value around that
+        node.
+
+        """
+
+        #reset minimum
+        self.__minimum_node = self.__reset_min
+        #down
+        if x < self.__height -1:
+            if self.__mapOfWorld[x + 1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x + 1][y] != self.__nothing:
+                #find the lowest number node, and exclude empty nodes (0's)
+                self.__minimum_node = self.__mapOfWorld[x + 1][y]
+                self.__min_node_location = 3
+        #up
+        if x > 0:
+            if self.__mapOfWorld[x-1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x-1][y] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x-1][y]
+                self.__min_node_location = 1
+        #right
+        if y < self.__width -1:
+            if self.__mapOfWorld[x][y + 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y + 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y + 1]
+                self.__min_node_location = 2
+        #left
+        if y > 0:
+            if self.__mapOfWorld[x][y - 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y - 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y-1]
+                self.__min_node_location = 4
+        return self.__minimum_node
+    ###########################################################################
+
+    def printMap(self):
+        """
+        Prints out the map of this instance of the class.
+
+        """
+
+        msg = ''
+        for temp_B in range(0, self.__height):
+            for temp_A in range(0, self.__width):
+                if self.__mapOfWorld[temp_B][temp_A] == self.__wall:
+                    msg += "%04s" % "[#]"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__robot:
+                    msg += "%04s" % "-"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__goal:
+                    msg += "%04s" % "G"
+                else:
+                    msg += "%04s" % str(self.__mapOfWorld[temp_B][temp_A])
+            msg += "\n\n"
+        msg += "\n\n"
+        print(msg)
+        #
+        if self.__slow == True:
+            time.sleep(0.05)
+############################################################################
+
+class mapCreate:   
+    ############################################################################
+ 
+    def create_map(self, scale,img):
+
+        print('Original Dimensions : ',img.shape)
+        
+        scale_percent = 100-scale # percent of original size
+        width = int(img.shape[1] * scale_percent / 100)
+        height = int(img.shape[0] * scale_percent / 100)
+        dim = (width, height)
+
+        # resize image
+        resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
+        print('Resized Dimensions : ',resized.shape)
+
+        gray = cv2.cvtColor(resized, cv2.COLOR_RGB2GRAY)
+        mask = cv2.inRange(gray, np.array([200]), np.array([255]))
+
+        mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+        mask_list= np.ndarray.tolist(mask)
+
+        #Markiere alle leeren Zellen mit 000 und alle Zellen mit Hinderniss mit 999
+        for i in range(0,mask.shape[0]):
+            mapOfWorld[i] = ['999' if j > 200 else '000' for j in mask_list[i]]
+        
+        mapOfWorld = np.array(mapOfWorld, dtype = int)
+        mapOfWorldSized = mapOfWorld.copy()
+        
+        e = 3
+        #Hindernisse Größer machen
+        for i in range(0,mapOfWorld.shape[0]):
+            for j in range(0,mapOfWorld.shape[1]):
+                for r in range(0,e):
+                    try:
+                        if (mapOfWorldSized[i][j] == 999):
+                            mapOfWorld[i][j+e] = 999
+                            mapOfWorld[i+e][j] = 999
+                            mapOfWorld[i-e][j] = 999
+                            mapOfWorld[i][j-e] = 999
+                            mapOfWorld[i+e][j+e] = 999
+                            mapOfWorld[i+e][j-e] = 999
+                            mapOfWorld[i-e][j+e] = 999
+                            mapOfWorld[i-e][j-e] = 999
+                    except Exception:
+                        continue
+
+        return mapOfWorld
+    ############################################################################
+
+    def scale_koord(self, sx, sy, gx, gy,scale):
+        scale_percent = 100-scale # percent of original size
+
+        sx = int(sx*scale_percent/100)
+        sy = int(sy*scale_percent/100)
+        gx = int(gx*scale_percent/100)
+        gy = int(gy*scale_percent/100)
+        
+        return sx,sy,gx,gy
+    ############################################################################
+
+    def rescale_koord(self, path,scale):
+        scale_percent = 100-scale # percent of original size100
+
+        path = np.array(path)
+
+        for i in range(len(path)):
+            path[i] = path[i]*100/scale_percent
+
+        return path
+    ############################################################################
+
+    def calc_trans(self, x, y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+###############################################################################
+
+if __name__ == "__main__":
+    """
+    X is vertical, Y is horizontal
+
+    """
+    
+    Map = mapCreate() #Map Objekt erzeugen
+    
+    #Verkleinerungsfaktor in %
+    scale = 90
+    
+    img = cv2.imread("D:/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/karte.jpg", cv2.COLOR_RGB2GRAY)
+    #cap = cv2.VideoCapture(2)
+    mapWorld = Map.create_map(scale, img)
+    height, width = img.shape[:2]
+    
+    #Angaben in Weltkoordinaten
+    sy = 300     #X-Koordinate im Weltkoordinaten System
+    sx = 200     #Y-Koordinate im Weltkoordinaten System
+    
+    gy = 700    #X-Koordinate im Weltkordinaten System
+    gx = 240    #Y-Koordinate im Weltkoordinaten System
+
+    sx,sy,gx,gy = Map.scale_koord(sx,sy,gx,gy,scale) #Kordinaten Tauschen X,Y
+
+    start = time.time()
+    planner = waveFrontPlanner(mapWorld)
+    planner.setGoalPosition(gx,gy)
+    planner.setRobotPosition(sx,sy)
+    path = planner.run(False)
+    end = time.time()
+    print("Took %f seconds to run wavefront simulation" % (end - start))
+
+    path = Map.rescale_koord(path, scale)
+    #print(path)
+#%% Plot 
+    #Programm Koordinaten
+    imgTrans = cv2.transpose(img) # X und Y-Achse im Bild tauschen
+    imgPlot, ax1 = plt.subplots()
+    
+    ax1.set_title('Programm Koordinaten')
+    ax1.imshow(imgTrans)
+    ax1.set_xlabel('[px]')
+    ax1.set_ylabel('[px]')
+    ax1.scatter(path[:,0], path[:,1], color='r')
+    
+    #Bild Koordinaten
+    imgPlot2, ax2 = plt.subplots()
+    ax2.set_title('Bild Koordinaten')
+    ax2.set_xlabel('[px]')
+    ax2.set_ylabel('[px]')
+    ax2.imshow(img)
+    ax2.scatter(path[:,1], path[:,0], color='r')
+    
+#%% Sphero Pfad
+    pathWeltX, pathWeltY = Map.calc_trans(path[:,1], path[:,0], height)
\ No newline at end of file
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__init__.py b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/_constants.cpython-310.pyc b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/_constants.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7a7dc990c992e83d0131942566db7b7d4f80a057
GIT binary patch
literal 2282
zcmd1j<>g{vU|?`?cT9Q1%fRp$#6iX&SqBCNhT=&K3=Am@Q4A@JDNHHMDJ&_hDQqe1
zDI6)BDO__nqZm`TQ+QH%Q<ziuQutE@=CDOEr3j`7r3lYqiegR?NfFItjABXQNfApC
zPmxHGoWl~u3f3W&BAp_W!k8kSBAX&Nha-v&Y>Ie_Sc-g#LW<%XwkY-#?i8^UrWC#u
z<`ktA<rLNwg%p)JoKYMps=*AJYKi-p85p>{^YY8{6arF<G7B<NixP7bLPI@Wiggt7
zlS&dZ^HNh3k}4GnOH+#~GxO3FN{c~cNk*!IQ%-4WL8U@&eoARhsuh<lH2{}mUP-2c
zi+`|!b4FrOVsc4pQD$*TX0n2ffq{XMfq{XkuBo|6nyyKjk%6wMvAKb+nT46Dxsh3#
zk)e^H9hXyLNl9u^rGigtS!xc387Q)LTu43+C`wIBEh<V)QE<-B%S%lz$;{7F2uLhS
z%uOvxEh@$^iFmDcT#f;r3SmYVMi>|v7=k>7-$O2Lp&%!f6y;-j2c#Q>@tfe6n45}W
zxl3wUW^$?mNY0MSv7jI|u_!Sw8B-lX%8m=<6wkc0d<?@tZZI$~Fv0JR;M5|poz5AF
zdFh~lMvGuHc{{GqylhayG{j|}F@F1?+HnRv0qtBN8L0|Isl_D<`DqHE<X)DTQ<_?=
zP@Gtnnxc@I2Np}o1gDh5qRiA{g{0J+{Bj+I^3<YKg{1tVqWtpI6os^+{9G=F%=D!E
zg3MI)Vuh^4vc%+~%z_eyoXn)6#G*<ah4PHd<P3$(Vui%A#LS$;q?}ZR#1e&!l9GaA
zD}DX+%#w`KB)#PPTz#l1`o*AZnqOw5msQNg^-_R=f#Ibfh!6%5Vjw~sL`Z-LNf03g
zBIFqu7&JL=@gx>x1{CEdrxq9I7v172t}HG|%>_m4EzW}c^3)<QlRc#<vn(?&{T5GR
zUS@7$Nl|`YW^(Z@w&K)0kS@;R{M^)%43Gl0(&E%2Pybsya3RM4&zGP=@FgS2RyGhJ
z1R^v*_Osm*%T3J8b1W#x$xKcJ<+8BUqT<Z_yjy}v`S~R|`H3m1MNpw4kk4*$!3{P-
zVw)kc&0qF{%)bFLpXnBFa7kiOiGNx^VsdtB$t`Zzyc9TxJuxT8$JM3yB_Buw6Nq2|
z5gZ_`EVsBai-S^&3-a@dQ*Q|rr52W^7MCDIBw-@{c{!D?MMe2VaK++9sl}-!#h!VI
z$t9U(nI)AWnYpR?r6n(!L8kM92v!gw2eOCb7H3LoYC&*LYHGnP)?zTlmjo%d!t!%U
z64O&}v6Lrfr-J=o1d2N(&l)4KO<uBtOyvQY%65yRD6!l(za+ot77y4t9;t~bpcvu>
z#bv5vaWFX5+~S0CgOYCvfSKW$B^hwF#U+VJnK_wN;HY^i0y3T-WIX3BE=b(_CKhMk
z;)Af^{ufHl&r8cpFD*)S&d<ro1jnaXGK}exT9TSvlA7XJT$z^)b(~Lraw5p7BB^<x
z1P|8+QNs=~-|!ZcVRTCrZbL9Q2?m!Gr6%V3X>#6TkB?8uPmYhj#gPIo(>z^n2?fIw
zwR3)MZem_a@h#!v)Vvf(nsCm~D=taQD=EGu07<-1MV>Cjw^-A164Q%s@q@Dhk~lvo
zs50}?p+d#5Ab{~#G86?cFhGc3A^I8lxvBc4Nu_xurTRtr#YXYv#rnlX$<Uk|pPQMN
z8K0b=2P)NbQj2g2gOosAs#j2Xi^B#|)7pXZRdE&r0|N^KlL!+dDrEb?#Dx%H`_078
l#K`uagPDm5BFgrci50?vk!(MiIALriMu-jsAH?GN0RU6~)o=g+

literal 0
HcmV?d00001

diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/core.cpython-310.pyc b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/core.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..268efa0a4ba0ab4916f275a675473967f0d05ef1
GIT binary patch
literal 19045
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
RfVO9GF!C`m)Ptay7XV!eD4zfT

literal 0
HcmV?d00001

diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/simple_moves.cpython-310.pyc b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/__pycache__/simple_moves.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1aac01a6d648c63bd3f5ffbf474fde28d479087f
GIT binary patch
literal 791
zcmd1j<>g{vU|^V=?v^r}g@NHQh=Yuo7#J8F7#J9eB^VeOQW&BbQW#U1au}l+Q<zg&
zS{S03Qka4nG+C>vxq>ru3vyBwa`Veli@9`>02fzCMrN@>ZhlH>PO3t3eqKppW?r#E
zT4`Q#NoIatu|i3{LPla)szOOdszPu<Mru*MLT+YWrb0@-LUDd>szNcs<lNM}l41po
zRK0XPh2+el<eXGZJ+7A^2m2*6f+#2ku~``y7@R>)KgPhoP{WV~aylc(`Mu1H3^fc3
z7*m)RGJ;u5DJ)PHa|$bz#j=nAEXSC_1{GmSVT7=tCb6V2K}}*!VNYRP$OKl8Fo89N
z5lNH-NiPeMD_B!FkyOEK$D%idA(%mv%dZIJHBIJQ%tfgww^-AQQd9G8u_Wb`rn<fS
z&%nU&l9_>lA>?HWhzU}eIp_cX|C(&KxQkOud|X|e^K<fxZt)hEBqn9%WL71DBH)&A
zacYTEVsf^RtBYq|NornkW=Z8Omh!~Rl3P4Qsl}-!9;t~bnR)5ASc>v<ax@ulu@!@3
zX(dCE00RTVuQ2_L{M=Oi(xlS7l2ZMm{9>c{@?!nsqGWxDx_D4*#)Bdrq(8L?r!Y94
z<H0FNub}c4ds==`d16rtD1{a)F)%O)FmW-0AP1NfVCG@uV&Y-qViaKFVdP@uVd7&f
z5@KLr&}6>F9v`2QpBx{5i@CV67%T{ODiR^cz`$^e!zLG;D(yf)Rm{e~z`(-5!Op`3
E0HgTKSO5S3

literal 0
HcmV?d00001

diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/_constants.py b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/_constants.py
new file mode 100644
index 0000000..fa8a0e8
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/_constants.py
@@ -0,0 +1,72 @@
+'''
+Known Peripheral UUIDs, obtained by querying using the Bluepy module:
+=====================================================================
+Anti DOS Characteristic <00020005-574f-4f20-5370-6865726f2121>
+Battery Level Characteristic <Battery Level>
+Peripheral Preferred Connection Parameters Characteristic <Peripheral Preferred Connection Parameters>
+API V2 Characteristic <00010002-574f-4f20-5370-6865726f2121>
+DFU Control Characteristic <00020002-574f-4f20-5370-6865726f2121>
+Name Characteristic <Device Name>
+Appearance Characteristic <Appearance>
+DFU Info Characteristic <00020004-574f-4f20-5370-6865726f2121>
+Service Changed Characteristic <Service Changed>
+Unknown1 Characteristic <00020003-574f-4f20-5370-6865726f2121>
+Unknown2 Characteristic <00010003-574f-4f20-5370-6865726f2121>
+
+The rest of the values saved in the dictionaries below, were borrowed from
+@igbopie's javacript library, which is available at https://github.com/igbopie/spherov2.js
+
+'''
+
+deviceID = {"apiProcessor": 0x10,                   # 16
+            "systemInfo": 0x11,                     # 17
+            "powerInfo": 0x13,                      # 19
+            "driving": 0x16,                        # 22
+            "animatronics": 0x17,                   # 23
+            "sensor": 0x18,                         # 24
+            "something": 0x19,                      # 25
+            "userIO": 0x1a,                         # 26
+            "somethingAPI": 0x1f}                   # 31
+
+SystemInfoCommands = {"mainApplicationVersion": 0x00,   # 00
+                      "bootloaderVersion": 0x01,    # 01
+                      "something": 0x06,            # 06
+                      "something2": 0x13,           # 19
+                      "something6": 0x12,           # 18    
+                      "something7": 0x28}           # 40
+
+sendPacketConstants = {"StartOfPacket": 0x8d,       # 141
+                       "EndOfPacket": 0xd8}         # 216
+
+userIOCommandIDs = {"allLEDs": 0x0e}                # 14
+
+flags= {"isResponse": 0x01,                         # 0x01
+        "requestsResponse": 0x02,                   # 0x02
+        "requestsOnlyErrorResponse": 0x04,          # 0x04
+        "resetsInactivityTimeout": 0x08}            # 0x08
+
+powerCommandIDs={"deepSleep": 0x00,                 # 0
+                "sleep": 0x01,                      # 01
+                "batteryVoltage": 0x03,             # 03
+                "wake": 0x0D,                       # 13
+                "something": 0x05,                  # 05 
+                "something2": 0x10,                 # 16         
+                "something3": 0x04,                 # 04
+                "something4": 0x1E}                 # 30
+
+drivingCommands={"rawMotor": 0x01,                  # 1
+                 "resetHeading": 0x06,              # 6    
+                 "driveAsSphero": 0x04,             # 4
+                 "driveAsRc": 0x02,                 # 2
+                 "driveWithHeading": 0x07,          # 7
+                 "stabilization": 0x0C}             # 12
+
+sensorCommands={'sensorMask': 0x00,                 # 00
+                'sensorResponse': 0x02,             # 02
+                'configureCollision': 0x11,         # 17
+                'collisionDetectedAsync': 0x12,     # 18
+                'resetLocator': 0x13,               # 19
+                'enableCollisionAsync': 0x14,       # 20
+                'sensor1': 0x0F,                    # 15
+                'sensor2': 0x17,                    # 23
+                'configureSensorStream': 0x0C}      # 12
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/blobErkennung.py b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/blobErkennung.py
new file mode 100644
index 0000000..4b0c0cd
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/blobErkennung.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+# Standard imports
+import cv2
+import numpy as np;
+ 
+# Img Objekt
+#cap = cv2.VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+cap = cv2.VideoCapture(4)
+
+# Set up the detector with default parameters.
+detector = cv2.SimpleBlobDetector()
+ 
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+params.filterByArea = True
+params.minArea = 20
+params.maxArea = 200
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+params.filterByInertia = True
+params.minInertiaRatio = 0.5
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+
+while True:
+
+    success, img = cap.read()
+    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+
+    # Detect blobs.
+    keypoints = detector.detect(gray)
+
+    #print(keypoints)
+    for keyPoint in keypoints:
+        x = keyPoint.pt[0]
+        y = keyPoint.pt[1]
+    
+    im_with_keypoints = cv2.drawKeypoints(gray, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
+
+    # Show blobs
+    cv2.imshow("Keypoints", im_with_keypoints)
+
+    if cv2.waitKey(10) & 0xFF == ord('q'):
+        break
\ No newline at end of file
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/coreROS2.py b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/coreROS2.py
new file mode 100644
index 0000000..ec34350
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/coreROS2.py
@@ -0,0 +1,638 @@
+from bluepy.btle import Peripheral
+from bluepy import btle
+from sphero_mini_controller._constants import *
+import struct
+import time
+import sys
+
+class SpheroMini():
+    def __init__(self, MACAddr, verbosity = 4, user_delegate = None):
+        '''
+        initialize class instance and then build collect BLE sevices and characteristics.
+        Also sends text string to Anti-DOS characteristic to prevent returning to sleep,
+        and initializes notifications (which is what the sphero uses to send data back to
+        the client).
+        '''
+        self.verbosity = verbosity # 0 = Silent,
+                                   # 1 = Connection/disconnection only
+                                   # 2 = Init messages
+                                   # 3 = Recieved commands
+                                   # 4 = Acknowledgements
+        self.sequence = 1
+        self.v_batt = None # will be updated with battery voltage when sphero.getBatteryVoltage() is called
+        self.firmware_version = [] # will be updated with firware version when sphero.returnMainApplicationVersion() is called
+
+        if self.verbosity > 0:
+            print("[INFO] Connecting to ", MACAddr)
+        self.p = Peripheral(MACAddr, "random") #connect
+
+        if self.verbosity > 1:
+            print("[INIT] Initializing")
+
+        # Subscribe to notifications
+        self.sphero_delegate = MyDelegate(self, user_delegate) # Pass a reference to this instance when initializing
+        self.p.setDelegate(self.sphero_delegate)
+
+        if self.verbosity > 1:
+            print("[INIT] Read all characteristics and descriptors")
+        # Get characteristics and descriptors
+        self.API_V2_characteristic = self.p.getCharacteristics(uuid="00010002-574f-4f20-5370-6865726f2121")[0]
+        self.AntiDOS_characteristic = self.p.getCharacteristics(uuid="00020005-574f-4f20-5370-6865726f2121")[0]
+        self.DFU_characteristic = self.p.getCharacteristics(uuid="00020002-574f-4f20-5370-6865726f2121")[0]
+        self.DFU2_characteristic = self.p.getCharacteristics(uuid="00020004-574f-4f20-5370-6865726f2121")[0]
+        self.API_descriptor = self.API_V2_characteristic.getDescriptors(forUUID=0x2902)[0]
+        self.DFU_descriptor = self.DFU_characteristic.getDescriptors(forUUID=0x2902)[0]
+
+        # The rest of this sequence was observed during bluetooth sniffing:
+        # Unlock code: prevent the sphero mini from going to sleep again after 10 seconds
+        if self.verbosity > 1:
+            print("[INIT] Writing AntiDOS characteristic unlock code")
+        self.AntiDOS_characteristic.write("usetheforce...band".encode(), withResponse=True)
+
+        # Enable DFU notifications:
+        if self.verbosity > 1:
+            print("[INIT] Configuring DFU descriptor")
+        self.DFU_descriptor.write(struct.pack('<bb', 0x01, 0x00), withResponse = True)
+
+        # No idea what this is for. Possibly a device ID of sorts? Read request returns '00 00 09 00 0c 00 02 02':
+        if self.verbosity > 1:
+            print("[INIT] Reading DFU2 characteristic")
+        _ = self.DFU2_characteristic.read()
+
+        # Enable API notifications:
+        if self.verbosity > 1:
+            print("[INIT] Configuring API dectriptor")
+        self.API_descriptor.write(struct.pack('<bb', 0x01, 0x00), withResponse = True)
+
+        self.wake()
+
+        # Finished initializing:
+        if self.verbosity > 1:
+            print("[INIT] Initialization complete\n")
+
+    def disconnect(self):
+        if self.verbosity > 0:
+            print("[INFO] Disconnecting")
+        
+        self.p.disconnect()
+
+    def wake(self):
+        '''
+        Bring device out of sleep mode (can only be done if device was in sleep, not deep sleep).
+        If in deep sleep, the device should be connected to USB power to wake.
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Waking".format(self.sequence))
+        
+        self._send(characteristic=self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=powerCommandIDs["wake"],
+                   payload=[]) # empty payload
+
+        self.getAcknowledgement("Wake")
+
+    def sleep(self, deepSleep=False):
+        '''
+        Put device to sleep or deep sleep (deep sleep needs USB power connected to wake up)
+        '''
+        if deepSleep:
+            sleepCommID=powerCommandIDs["deepSleep"]
+            if self.verbosity > 0:
+                print("[INFO] Going into deep sleep. Connect USB power to wake.")
+        else:
+            sleepCommID=powerCommandIDs["sleep"]
+        self._send(characteristic=self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=sleepCommID,
+                   payload=[]) #empty payload
+
+    def setLEDColor(self, red = None, green = None, blue = None):
+        '''
+        Set device LED color based on RGB vales (each can  range between 0 and 0xFF)
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Setting main LED colour to [{}, {}, {}]".format(self.sequence, red, green, blue))
+        
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['userIO'], # 0x1a
+                  commID = userIOCommandIDs["allLEDs"], # 0x0e
+                  payload = [0x00, 0x0e, red, green, blue])
+
+        self.getAcknowledgement("LED/backlight")
+
+    def setBackLEDIntensity(self, brightness=None):
+        '''
+        Set device LED backlight intensity based on 0-255 values
+
+        NOTE: this is not the same as aiming - it only turns on the LED
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Setting backlight intensity to {}".format(self.sequence, brightness))
+
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['userIO'],
+                  commID = userIOCommandIDs["allLEDs"],
+                  payload = [0x00, 0x01, brightness])
+
+        self.getAcknowledgement("LED/backlight")
+
+    def roll(self, speed=None, heading=None):
+        '''
+        Start to move the Sphero at a given direction and speed.
+        heading: integer from 0 - 360 (degrees)
+        speed: Integer from 0 - 255
+
+        Note: the zero heading should be set at startup with the resetHeading method. Otherwise, it may
+        seem that the sphero doesn't honor the heading argument
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Rolling with speed {} and heading {}".format(self.sequence, speed, heading))
+    
+        if abs(speed) > 255:
+            print("WARNING: roll speed parameter outside of allowed range (-255 to +255)")
+
+        if speed < 0:
+            speed = -1*speed+256 # speed values > 256 in the send packet make the spero go in reverse
+
+        speedH = (speed & 0xFF00) >> 8
+        speedL = speed & 0xFF
+        headingH = (heading & 0xFF00) >> 8
+        headingL = heading & 0xFF
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['driving'],
+                  commID = drivingCommands["driveWithHeading"],
+                  payload = [speedL, headingH, headingL, speedH])
+
+        self.getAcknowledgement("Roll")
+
+    def resetHeading(self):
+        '''
+        Reset the heading zero angle to the current heading (useful during aiming)
+        Note: in order to manually rotate the sphero, you need to call stabilization(False).
+        Once the heading has been set, call stabilization(True).
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Resetting heading".format(self.sequence))
+    
+        self._send(characteristic = self.API_V2_characteristic,
+                  devID = deviceID['driving'],
+                  commID = drivingCommands["resetHeading"],
+                  payload = []) #empty payload
+
+        self.getAcknowledgement("Heading")
+
+    def returnMainApplicationVersion(self):
+        '''
+        Sends command to return application data in a notification
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Requesting firmware version".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID = deviceID['systemInfo'],
+                   commID = SystemInfoCommands['mainApplicationVersion'],
+                   payload = []) # empty
+
+        self.getAcknowledgement("Firmware")
+
+    def getBatteryVoltage(self):
+        '''
+        Sends command to return battery voltage data in a notification.
+        Data printed to console screen by the handleNotifications() method in the MyDelegate class.
+        '''
+        if self.verbosity > 2:
+            print("[SEND {}] Requesting battery voltage".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['powerInfo'],
+                   commID=powerCommandIDs['batteryVoltage'],
+                   payload=[]) # empty
+
+        self.getAcknowledgement("Battery")
+
+    def stabilization(self, stab = True):
+        '''
+        Sends command to turn on/off the motor stabilization system (required when manually turning/aiming the sphero)
+        '''
+        if stab == True:
+            if self.verbosity > 2:
+                    print("[SEND {}] Enabling stabilization".format(self.sequence))
+            val = 1
+        else:
+            if self.verbosity > 2:
+                    print("[SEND {}] Disabling stabilization".format(self.sequence))
+            val = 0
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['driving'],
+                   commID=drivingCommands['stabilization'],
+                   payload=[val])
+
+        self.getAcknowledgement("Stabilization")
+
+    def wait(self, delay):
+        '''
+        This is a non-blocking delay command. It is similar to time.sleep(), except it allows asynchronous 
+        notification handling to still be performed.
+        '''
+        start = time.time()
+        while(1):
+            self.p.waitForNotifications(0.001)
+            if time.time() - start > delay:
+                break
+
+    def _send(self, characteristic=None, devID=None, commID=None, payload=[]):
+        '''
+        A generic "send" method, which will be used by other methods to send a command ID, payload and
+        appropriate checksum to a specified device ID. Mainly useful because payloads are optional,
+        and can be of varying length, to convert packets to binary, and calculate and send the
+        checksum. For internal use only.
+
+        Packet structure has the following format (in order):
+
+        - Start byte: always 0x8D
+        - Flags byte: indicate response required, etc
+        - Virtual device ID: see _constants.py
+        - Command ID: see _constants.py
+        - Sequence number: Seems to be arbitrary. I suspect it is used to match commands to response packets (in which the number is echoed).
+        - Payload: Could be varying number of bytes (incl. none), depending on the command
+        - Checksum: See below for calculation
+        - End byte: always 0xD8
+
+        '''
+        sendBytes = [sendPacketConstants["StartOfPacket"],
+                    sum([flags["resetsInactivityTimeout"], flags["requestsResponse"]]),
+                    devID,
+                    commID,
+                    self.sequence] + payload # concatenate payload list
+
+        self.sequence += 1 # Increment sequence number, ensures we can identify response packets are for this command
+        if self.sequence > 255:
+            self.sequence = 0
+
+        # Compute and append checksum and add EOP byte:
+        # From Sphero docs: "The [checksum is the] modulo 256 sum of all the bytes
+        #                   from the device ID through the end of the data payload,
+        #                   bit inverted (1's complement)"
+        # For the sphero mini, the flag bits must be included too:
+        checksum = 0
+        for num in sendBytes[1:]:
+            checksum = (checksum + num) & 0xFF # bitwise "and to get modulo 256 sum of appropriate bytes
+        checksum = 0xff - checksum # bitwise 'not' to invert checksum bits
+        sendBytes += [checksum, sendPacketConstants["EndOfPacket"]] # concatenate
+
+        # Convert numbers to bytes
+        output = b"".join([x.to_bytes(1, byteorder='big') for x in sendBytes])
+
+        #send to specified characteristic:
+        characteristic.write(output, withResponse = True)
+
+    def getAcknowledgement(self, ack):
+        #wait up to 10 secs for correct acknowledgement to come in, including sequence number!
+        start = time.time()
+        while(1):
+            self.p.waitForNotifications(1)
+            if self.sphero_delegate.notification_seq == self.sequence-1: # use one less than sequence, because _send function increments it for next send. 
+                if self.verbosity > 3:
+                    print("[RESP {}] {}".format(self.sequence-1, self.sphero_delegate.notification_ack))
+                self.sphero_delegate.clear_notification()
+                break
+            elif self.sphero_delegate.notification_seq >= 0:
+                print("Unexpected ACK. Expected: {}/{}, received: {}/{}".format(
+                    ack, self.sequence, self.sphero_delegate.notification_ack.split()[0],
+                    self.sphero_delegate.notification_seq)
+                    )
+            if time.time() > start + 10:
+                print("Timeout waiting for acknowledgement: {}/{}".format(ack, self.sequence))
+                break
+
+# =======================================================================
+# The following functions are experimental:
+# =======================================================================
+
+    def configureCollisionDetection(self,
+                                     xThreshold = 50, 
+                                     yThreshold = 50, 
+                                     xSpeed = 50, 
+                                     ySpeed = 50, 
+                                     deadTime = 50, # in 10 millisecond increments
+                                     method = 0x01, # Must be 0x01        
+                                     callback = None):
+        '''
+        Appears to function the same as other Sphero models, however speed settings seem to have no effect. 
+        NOTE: Setting to zero seems to cause bluetooth errors with the Sphero Mini/bluepy library - set to 
+        255 to make it effectively disabled.
+
+        deadTime disables future collisions for a short period of time to avoid repeat triggering by the same
+        event. Set in 10ms increments. So if deadTime = 50, that means the delay will be 500ms, or half a second.
+        
+        From Sphero docs:
+        
+            xThreshold/yThreshold: An 8-bit settable threshold for the X (left/right) and Y (front/back) axes 
+            of Sphero.
+
+            xSpeed/ySpeed: An 8-bit settable speed value for the X and Y axes. This setting is ranged by the 
+            speed, then added to xThreshold, yThreshold to generate the final threshold value.
+        '''
+        
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring collision detection".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['configureCollision'],
+                   payload=[method, xThreshold, xSpeed, yThreshold, ySpeed, deadTime])
+
+        self.collision_detection_callback = callback
+
+        self.getAcknowledgement("Collision")
+
+    def configureSensorStream(self): # Use default values
+        '''
+        Send command to configure sensor stream using default values as found during bluetooth 
+        sniffing of the Sphero Edu app.
+
+        Must be called after calling configureSensorMask()
+        '''
+        bitfield1 = 0b00000000 # Unknown function - needs experimenting
+        bitfield2 = 0b00000000 # Unknown function - needs experimenting
+        bitfield3 = 0b00000000 # Unknown function - needs experimenting
+        bitfield4 = 0b00000000 # Unknown function - needs experimenting
+
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring sensor stream".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['configureSensorStream'],
+                   payload=[bitfield1, bitfield1, bitfield1, bitfield1])
+
+        self.getAcknowledgement("Sensor")
+
+    def configureSensorMask(self,
+                            sample_rate_divisor = 0x25, # Must be > 0
+                            packet_count = 0,
+                            IMU_pitch = False,
+                            IMU_roll = False,
+                            IMU_yaw = False,
+                            IMU_acc_x = False,
+                            IMU_acc_y = False,
+                            IMU_acc_z = False,
+                            IMU_gyro_x = False,
+                            IMU_gyro_y = False,
+                            IMU_gyro_z = False):
+
+        '''
+        Send command to configure sensor mask using default values as found during bluetooth 
+        sniffing of the Sphero Edu app. From experimentation, it seems that these are he functions of each:
+        
+        Sampling_rate_divisor. Slow data EG: Set to 0x32 to the divide data rate by 50. Setting below 25 (0x19) causes 
+                bluetooth errors        
+        
+        Packet_count: Select the number of packets to transmit before ending the stream. Set to zero to stream infinitely
+        
+        All IMU bool parameters: Toggle transmission of that value on or off (e.g. set IMU_acc_x = True to include the 
+                X-axis accelerometer readings in the sensor stream)
+        '''
+
+        # Construct bitfields based on function parameters:
+        IMU_bitfield1 = (IMU_pitch<<2) + (IMU_roll<<1) + IMU_yaw
+        IMU_bitfield2 = ((IMU_acc_y<<7) + (IMU_acc_z<<6) + (IMU_acc_x<<5) + \
+                         (IMU_gyro_y<<4) + (IMU_gyro_x<<2) + (IMU_gyro_z<<2))
+        
+        if self.verbosity > 2:
+            print("[SEND {}] Configuring sensor mask".format(self.sequence))
+    
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensorMask'],
+                   payload=[0x00,               # Unknown param - altering it seems to slow data rate. Possibly averages multiple readings?
+                            sample_rate_divisor,       
+                            packet_count,       # Packet count: select the number of packets to stop streaming after (zero = infinite)
+                            0b00,               # Unknown param: seems to be another accelerometer bitfield? Z-acc, Y-acc
+                            IMU_bitfield1,
+                            IMU_bitfield2,
+                            0b00])              # reserved, Position?, Position?, velocity?, velocity?, Y-gyro, timer, reserved
+
+        self.getAcknowledgement("Mask")
+
+        '''
+        Since the sensor values arrive as unlabelled lists in the order that they appear in the bitfields above, we need 
+        to create a list of sensors that have been configured.Once we have this list, then in the default_delegate class, 
+        we can get sensor values as attributes of the sphero_mini class.
+        e.g. print(sphero.IMU_yaw) # displays the current yaw angle
+        '''
+
+        # Initialize dictionary with sensor names as keys and their bool values (set by the user) as values:
+        availableSensors = {"IMU_pitch" : IMU_pitch,
+                            "IMU_roll" : IMU_roll,
+                            "IMU_yaw" : IMU_yaw,
+                            "IMU_acc_y" : IMU_acc_y,
+                            "IMU_acc_z" : IMU_acc_z,
+                            "IMU_acc_x" : IMU_acc_x,
+                            "IMU_gyro_y" : IMU_gyro_y,
+                            "IMU_gyro_x" : IMU_gyro_x,
+                            "IMU_gyro_z" : IMU_gyro_z}
+        
+        # Create list of of only sensors that have been "activated" (set as true in the method arguments):
+        self.configured_sensors = [name for name in availableSensors if availableSensors[name] == True]
+
+    def sensor1(self): # Use default values
+        '''
+        Unknown function. Observed in bluetooth sniffing. 
+        '''
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensor1'],
+                   payload=[0x01])
+
+        self.getAcknowledgement("Sensor1")
+
+    def sensor2(self): # Use default values
+        '''
+        Unknown function. Observed in bluetooth sniffing. 
+        '''
+        self._send(self.API_V2_characteristic,
+                   devID=deviceID['sensor'],
+                   commID=sensorCommands['sensor2'],
+                   payload=[0x00])
+
+        self.getAcknowledgement("Sensor2")
+
+# =======================================================================
+
+class MyDelegate(btle.DefaultDelegate):
+
+    '''
+    This class handles notifications (both responses and asynchronous notifications).
+    
+    Usage of this class is described in the Bluepy documentation
+    
+    '''
+
+    def __init__(self, sphero_class, user_delegate):
+        self.sphero_class = sphero_class # for saving sensor values as attributes of sphero class instance
+        self.user_delegate = user_delegate # to directly notify users of callbacks
+        btle.DefaultDelegate.__init__(self)
+        self.clear_notification()
+        self.notificationPacket = []
+
+    def clear_notification(self):
+        self.notification_ack = "DEFAULT ACK"
+        self.notification_seq = -1
+
+    def bits_to_num(self, bits):
+        '''
+        This helper function decodes bytes from sensor packets into single precision floats. Encoding follows the
+        the IEEE-754 standard.
+        '''
+        num = int(bits, 2).to_bytes(len(bits) // 8, byteorder='little')
+        num = struct.unpack('f', num)[0]
+        return num
+
+    def handleNotification(self, cHandle, data):
+        '''
+        This method acts as an interrupt service routine. When a notification comes in, this
+        method is invoked, with the variable 'cHandle' being the handle of the characteristic that
+        sent the notification, and 'data' being the payload (sent one byte at a time, so the packet
+        needs to be reconstructed)  
+
+        The method keeps appending bytes to the payload packet byte list until end-of-packet byte is
+        encountered. Note that this is an issue, because 0xD8 could be sent as part of the payload of,
+        say, the battery voltage notification. In future, a more sophisticated method will be required.
+        '''
+        # Allow the user to intercept and process data first..
+        if self.user_delegate != None:
+            if self.user_delegate.handleNotification(cHandle, data):
+                return
+        
+        #print("Received notification with packet ", str(data))
+
+        for data_byte in data: # parse each byte separately (sometimes they arrive simultaneously)
+
+            self.notificationPacket.append(data_byte) # Add new byte to packet list
+
+            # If end of packet (need to find a better way to segment the packets):
+            if data_byte == sendPacketConstants['EndOfPacket']:
+                # Once full the packet has arrived, parse it:
+                # Packet structure is similar to the outgoing send packets (see docstring in sphero_mini._send())
+                
+                # Attempt to unpack. Might fail if packet is too badly corrupted
+                try:
+                    start, flags_bits, devid, commcode, seq, *notification_payload, chsum, end = self.notificationPacket
+                except ValueError:
+                    print("Warning: notification packet unparseable ", self.notificationPacket)
+                    self.notificationPacket = [] # Discard this packet
+                    return # exit
+
+                # Compute and append checksum and add EOP byte:
+                # From Sphero docs: "The [checksum is the] modulo 256 sum of all the bytes
+                #                   from the device ID through the end of the data payload,
+                #                   bit inverted (1's complement)"
+                # For the sphero mini, the flag bits must be included too:
+                checksum_bytes = [flags_bits, devid, commcode, seq] + notification_payload
+                checksum = 0 # init
+                for num in checksum_bytes:
+                    checksum = (checksum + num) & 0xFF # bitwise "and to get modulo 256 sum of appropriate bytes
+                checksum = 0xff - checksum # bitwise 'not' to invert checksum bits
+                if checksum != chsum: # check computed checksum against that recieved in the packet
+                    print("Warning: notification packet checksum failed - ", str(self.notificationPacket))
+                    self.notificationPacket = [] # Discard this packet
+                    return # exit
+
+                # Check if response packet:
+                if flags_bits & flags['isResponse']: # it is a response
+
+                    # Use device ID and command code to determine which command is being acknowledged:
+                    if devid == deviceID['powerInfo'] and commcode == powerCommandIDs['wake']:
+                        self.notification_ack = "Wake acknowledged" # Acknowledgement after wake command
+                        
+                    elif devid == deviceID['driving'] and commcode == drivingCommands['driveWithHeading']:
+                        self.notification_ack = "Roll command acknowledged"
+
+                    elif devid == deviceID['driving'] and commcode == drivingCommands['stabilization']:
+                        self.notification_ack = "Stabilization command acknowledged"
+
+                    elif devid == deviceID['userIO'] and commcode == userIOCommandIDs['allLEDs']:
+                        self.notification_ack = "LED/backlight color command acknowledged"
+
+                    elif devid == deviceID['driving'] and commcode == drivingCommands["resetHeading"]:
+                        self.notification_ack = "Heading reset command acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["configureCollision"]:
+                        self.notification_ack = "Collision detection configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["configureSensorStream"]:
+                        self.notification_ack = "Sensor stream configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensorMask"]:
+                        self.notification_ack = "Mask configuration acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensor1"]:
+                        self.notification_ack = "Sensor1 acknowledged"
+
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands["sensor2"]:
+                        self.notification_ack = "Sensor2 acknowledged"
+
+                    elif devid == deviceID['powerInfo'] and commcode == powerCommandIDs['batteryVoltage']:
+                        V_batt = notification_payload[2] + notification_payload[1]*256 + notification_payload[0]*65536
+                        V_batt /= 100 # Notification gives V_batt in 10mV increments. Divide by 100 to get to volts.
+                        self.notification_ack = "Battery voltage:" + str(V_batt) + "v"
+                        self.sphero_class.v_batt = V_batt
+
+                    elif devid == deviceID['systemInfo'] and commcode == SystemInfoCommands['mainApplicationVersion']:
+                        version = '.'.join(str(x) for x in notification_payload)
+                        self.notification_ack = "Firmware version: " + version
+                        self.sphero_class.firmware_version = notification_payload
+                                                
+                    else:
+                        self.notification_ack = "Unknown acknowledgement" #print(self.notificationPacket)
+                        print(self.notificationPacket, "===================> Unknown ack packet")
+
+                    self.notification_seq = seq
+
+                else: # Not a response packet - therefore, asynchronous notification (e.g. collision detection, etc):
+                    
+                    # Collision detection:
+                    if devid == deviceID['sensor'] and commcode == sensorCommands['collisionDetectedAsync']:
+                        # The first four bytes are data that is still un-parsed. the remaining unsaved bytes are always zeros
+                        _, _, _, _, _, _, axis, _, Y_mag, _, X_mag, *_ = notification_payload
+                        if axis == 1: 
+                            dir = "Left/right"
+                        else:
+                            dir = 'Forward/back'
+                        print("Collision detected:")
+                        print("\tAxis: ", dir)
+                        print("\tX_mag: ", X_mag)
+                        print("\tY_mag: ", Y_mag)
+
+                        if self.sphero_class.collision_detection_callback is not None:
+                            self.notificationPacket = [] # need to clear packet, in case new notification comes in during callback
+                            self.sphero_class.collision_detection_callback()
+
+                    # Sensor response:
+                    elif devid == deviceID['sensor'] and commcode == sensorCommands['sensorResponse']:
+                        # Convert to binary, pad bytes with leading zeros:
+                        val = ''
+                        for byte in notification_payload:
+                            val += format(int(bin(byte)[2:], 2), '#010b')[2:]
+                        
+                        # Break into 32-bit chunks
+                        nums = []
+                        while(len(val) > 0):
+                            num, val = val[:32], val[32:] # Slice off first 16 bits
+                            nums.append(num)
+                        
+                        # convert from raw bits to float:
+                        nums = [self.bits_to_num(num) for num in nums]
+
+                        # Set sensor values as class attributes:
+                        for name, value in zip(self.sphero_class.configured_sensors, nums):
+                            print("Setting sensor  at .", name, str(value))
+                            setattr(self.sphero_class, name, value)
+                        
+                    # Unrecognized packet structure:
+                    else:
+                        self.notification_ack = "Unknown asynchronous notification" #print(self.notificationPacket)
+                        print(str(self.notificationPacket) + " ===================> Unknown async packet")
+                        
+                self.notificationPacket = [] # Start new payload after this byte
\ No newline at end of file
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/karte.jpg b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/karte.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2dfab8ae944dcd069b9970cebe77965f549b21a0
GIT binary patch
literal 161695
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
A!~g&Q

literal 0
HcmV?d00001

diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/sphero_conf.json b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/sphero_conf.json
new file mode 100644
index 0000000..a490b4b
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/sphero_conf.json
@@ -0,0 +1,3 @@
+{
+    "MAC_ADDRESS": "C6:69:72:CD:BC:6D"
+}
diff --git a/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/sphero_mini.py b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/sphero_mini.py
new file mode 100644
index 0000000..2dd16aa
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/sphero_mini.py
@@ -0,0 +1,756 @@
+#!/usr/bin/env python3
+############################################################################
+#%% Imports
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Imu
+import threading
+from geometry_msgs.msg import Quaternion, Vector3
+import numpy as np
+from sphero_mini_controller.coreROS2 import SpheroMini 
+import cv2
+import time
+import queue
+import matplotlib.pyplot as plt
+############################################################################
+#%% Blob Detector / Globale Variablen
+detector = cv2.SimpleBlobDetector()
+ 
+# Setup SimpleBlobDetector parameters.
+params = cv2.SimpleBlobDetector_Params()
+
+# Change thresholds
+#params.minThreshold = 5
+#params.maxThreshold = 500
+
+#FIlter by Color
+params.filterByColor = True
+params.blobColor = 255
+
+# Filter by Area.
+params.filterByArea = True
+params.minArea = 10
+params.maxArea = 200
+
+# Filter by Circularity
+#params.filterByCircularity = True
+#params.minCircularity = 0.5
+#params.maxCircularity = 1
+
+# Filter by Convexity
+#params.filterByConvexity = True
+#params.minConvexity = 0.7
+#params.maxConvexity = 1
+
+# Filter by Inertia
+#params.filterByInertia = True
+#params.minInertiaRatio = 0.01
+
+# Create a detector with the parameters
+detector = cv2.SimpleBlobDetector_create(params)
+############################################################################
+#%% Class Video Capture
+# Bufferless VideoCapture
+# Quelle ?
+class VideoCapture:
+  def __init__(self, name):
+    self.cap = cv2.VideoCapture(name)
+    self.q = queue.Queue()
+    t = threading.Thread(target=self._reader)
+    t.daemon = True
+    t.start()
+  # read frames as soon as they are available, keeping only most recent one
+  def _reader(self):
+    while True:
+        ret, frame = self.cap.read()
+        #cv2.imshow("Cap", frame)
+
+        if not ret:
+            break
+        if not self.q.empty():
+            try:
+                self.q.get_nowait()   # discard previous (unprocessed) frame
+            except queue.Empty:
+                pass
+        self.q.put(frame)
+
+  def read(self):
+    return self.q.get()
+############################################################################
+#%% Class Sphero Node
+class MyNode(Node):
+    def __init__(self):
+        super().__init__("sphero_mini")
+    
+    def connect(self):
+        MAC_ADDRESS = "C6:69:72:CD:BC:6D"
+
+        # Connect:
+        sphero = SpheroMini(MAC_ADDRESS, verbosity = 4)
+        # battery voltage
+        sphero.getBatteryVoltage()
+        print(f"Bettery voltage: {sphero.v_batt}v")
+
+        # firmware version number
+        sphero.returnMainApplicationVersion()
+        print(f"Firmware version: {'.'.join(str(x) for x in sphero.firmware_version)}")
+        return sphero
+
+    def create_quaternion(self, roll, pitch, yaw):
+        q = Quaternion()
+        cy, sy = np.cos(yaw * 0.5), np.sin(yaw * 0.5)
+        cp, sp = np.cos(pitch * 0.5), np.sin(pitch * 0.5)
+        cr, sr = np.cos(roll * 0.5), np.sin(roll * 0.5)
+
+        q.w = cr * cp * cy + sr * sp * sy
+        q.x = sr * cp * cy - cr * sp * sy
+        q.y = cr * sp * cy + sr * cp * sy
+        q.z = cr * cp * sy - sr * sp * cy
+
+        return q
+
+    def create_angular_veolocity_vector3(self, groll, gpitch, gyaw):
+        v = Vector3()
+        v.x = groll
+        v.y = gpitch
+        v.z = float(gyaw)
+
+        return v
+
+    def create_linear_acc_vector3(self, xacc, yacc, zacc):
+        v = Vector3()
+        v.x = xacc
+        v.y = yacc
+        v.z = zacc
+
+        return v
+
+    def get_sensors_data(self, sphero):
+        return {
+            "roll": sphero.IMU_roll,
+            "pitch": sphero.IMU_pitch,
+            "yaw": sphero.IMU_yaw,
+            "groll": sphero.IMU_gyro_x,
+            "gpitch": sphero.IMU_gyro_y,
+            "xacc": sphero.IMU_acc_x,
+            "yacc": sphero.IMU_acc_y,
+            "zacc": sphero.IMU_acc_z
+        }
+        
+    def publish_imu(self, sensors_values,node):
+        i = Imu()
+
+        i.header.stamp = node.get_clock().now().to_msg()
+
+        i.orientation = self.create_quaternion(
+            roll=sensors_values["roll"],
+            pitch=sensors_values["pitch"],
+            yaw=sensors_values["yaw"]
+            )
+        i.angular_velocity = self.create_angular_veolocity_vector3(
+            groll=sensors_values["groll"],
+            gpitch=sensors_values["gpitch"],
+            gyaw=0  # We don't have the IMU_gyro_z
+        )
+        i.linear_acceleration = self.create_linear_acc_vector3(
+            xacc=sensors_values["xacc"],
+            yacc=sensors_values["yacc"],
+            zacc=sensors_values["zacc"]
+        )
+
+    def get_pos(self, cap, height):
+        #zeitanfang = time.time()
+        
+        success = False
+
+        while(success == False):
+            try:
+                img = cap.read()
+
+                gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY )
+                keypoints = detector.detect(gray)
+
+                for keyPoint in keypoints:
+                    x = keyPoint.pt[0]
+                    y = keyPoint.pt[1]
+                    success = True
+
+                xTrans, yTrans = self.calc_trans(x,y, height)
+            except Exception:
+                continue
+
+        #zeitende = time.time()
+        #print("Dauer Programmausführung:",(zeitende-zeitanfang))
+        #print("Get_Pos: X,Y:", xTrans,yTrans)
+
+        return xTrans,yTrans
+
+    def calc_offset(self, sphero, cap, height):
+        sphero.roll(100,0)
+        sphero.wait(1)
+        sphero.roll(0,0)
+        sphero.wait(0.5)
+
+        ref =  self.get_pos(cap, height)
+        print("calc_offset: Ref Punkt x,y", ref)
+
+        sphero.wait(1)
+        sphero.roll(100,180)
+        sphero.wait(1)
+        sphero.roll(0,0)
+
+        startpunkt = self.get_pos(cap, height)
+        print("calc_offset: Startpunkt x,y", startpunkt)
+
+        ref = np.array(ref)
+        startpunkt = np.array(startpunkt)
+
+        start_ref = ref-startpunkt
+
+        phi = np.arctan2(start_ref[1],start_ref[0])
+        phi = np.degrees(phi)
+        phi = int(-phi)
+        
+        print("Phi ohne alles:", phi)
+
+        phi = self.phi_in_range(phi)   
+
+        print("Calc_Offset: ", phi)
+
+        return phi
+
+    def calc_av(self,startPos, sollPos, cap, height):    
+        startPos = np.array(startPos)
+        sollPos = np.array(sollPos)
+
+        pktSpheroKord = sollPos - startPos
+
+        phi = np.arctan2(pktSpheroKord[1], pktSpheroKord[0])
+        phi = np.degrees(phi)
+
+        phiZiel = int(phi)
+
+        phiZiel = self.phi_in_range(phiZiel)
+
+        v = 100
+
+        #print("Calc_AV: a,v", phiZiel, v)
+
+        return phiZiel, v
+    
+    def drive_to(self,sphero, targetPos, aOffset, cap, height):
+        dmin = 20
+        pos = self.get_pos(cap, height)
+        pos = np.array(pos)
+
+        diff = targetPos - pos
+
+        d = np.linalg.norm(diff, ord = 2)
+
+        ar = []
+        ar.append(0)
+            
+        i = 1
+
+        while d > dmin:
+            a,v = self.calc_av(pos,targetPos, cap, height)
+
+            aR = -aOffset - a 
+            ar.append((self.phi_in_range(aR)))
+            
+            #Fahrbefehl
+            if(ar[i] != ar[i-1]):
+                sphero.roll(v, ar[i])
+                sphero.wait(0.05)
+            else:
+                sphero.wait(0.05)
+                
+            #Aktuelle Pos
+            pos = self.get_pos(cap, height)
+            pos = np.array(pos)
+            
+            #Abweichung
+            diff = targetPos - pos
+            diff = np.array(diff)
+            d = np.linalg.norm(diff, ord = 2)
+
+            i = i + 1
+
+        sphero.roll(0,0)
+        print("Ziel Erreicht")
+
+        return
+
+    def calc_trans(self,x,y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+    
+    def phi_in_range(self,phi):    
+        while(phi < 0):
+            phi = phi + 360 
+        while(phi > 360):
+            phi = phi - 360 
+        return phi  
+############################################################################
+#%% Class Wavefrontplanner
+class waveFrontPlanner:
+    ############################################################################
+    # WAVEFRONT ALGORITHM
+    # Adapted to Python Code By Darin Velarde
+    # Fri Jan 29 13:56:53 PST 2010
+    # from C code from John Palmisano 
+    # (www.societyofrobots.com)
+    ############################################################################
+
+    def __init__(self, mapOfWorld, slow=False):
+        self.__slow = slow
+        self.__mapOfWorld = mapOfWorld
+        if str(type(mapOfWorld)).find("numpy") != -1:
+            #If its a numpy array
+            self.__height, self.__width = self.__mapOfWorld.shape
+        else:
+            self.__height, self.__width = len(self.__mapOfWorld), len(self.__mapOfWorld[0])
+
+        self.__nothing = 000
+        self.__wall = 999
+        self.__goal = 1
+        self.__path = "PATH"
+
+        self.__finalPath = []
+
+        #Robot value
+        self.__robot = 254
+        #Robot default Location
+        self.__robot_x = 0
+        self.__robot_y = 0
+
+        #default goal location
+        self.__goal_x = 8
+        self.__goal_y = 9
+
+        #temp variables
+        self.__temp_A = 0
+        self.__temp_B = 0
+        self.__counter = 0
+        self.__steps = 0 #determine how processor intensive the algorithm was
+
+        #when searching for a node with a lower value
+        self.__minimum_node = 250
+        self.__min_node_location = 250
+        self.__new_state = 1
+        self.__old_state = 1
+        self.__reset_min = 250 #above this number is a special (wall or robot)
+    ###########################################################################
+
+    def setRobotPosition(self, x, y):
+        """
+        Sets the robot's current position
+
+        """
+
+        self.__robot_x = x
+        self.__robot_y = y
+    ###########################################################################
+
+    def setGoalPosition(self, x, y):
+        """
+        Sets the goal position.
+
+        """
+
+        self.__goal_x = x
+        self.__goal_y = y
+    ###########################################################################
+
+    def robotPosition(self):
+        return  (self.__robot_x, self.__robot_y)
+    ###########################################################################
+
+    def goalPosition(self):
+        return  (self.__goal_x, self.__goal_y)
+    ###########################################################################
+
+    def run(self, prnt=False):
+        """
+        The entry point for the robot algorithm to use wavefront propagation.
+
+        """
+
+        path = []
+        while self.__mapOfWorld[self.__robot_x][self.__robot_y] != self.__goal:
+            if self.__steps > 20000:
+                print ("Cannot find a path.")
+                return
+            #find new location to go to
+            self.__new_state = self.propagateWavefront()
+            #update location of robot
+            if self.__new_state == 1:
+                self.__robot_x -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" % (self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 2:
+                self.__robot_y += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 3:
+                self.__robot_x += 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            if self.__new_state == 4:
+                self.__robot_y -= 1
+                if prnt:
+                    print("Move to x=%d y=%d\n\n" %(self.__robot_x, self.__robot_y))
+                path.append((self.__robot_x, self.__robot_y))
+            self.__old_state = self.__new_state
+        msg = "Found the goal in %i steps:\n" % self.__steps
+        msg += "mapOfWorld size= %i %i\n\n" % (self.__height, self.__width)
+        if prnt:
+            print(msg)
+            self.printMap()
+        return path
+    ###########################################################################
+
+    def propagateWavefront(self, prnt=False):
+        self.unpropagate()
+        #Old robot location was deleted, store new robot location in mapOfWorld
+        self.__mapOfWorld[self.__robot_x][self.__robot_y] = self.__robot
+        self.__path = self.__robot
+        #start location to begin scan at goal location
+        self.__mapOfWorld[self.__goal_x][self.__goal_y] = self.__goal
+        counter = 0
+        while counter < 200:  #allows for recycling until robot is found
+            x = 0
+            y = 0
+            #time.sleep(0.00001)
+            #while the mapOfWorld hasnt been fully scanned
+            while x < self.__height and y < self.__width:
+                #if this location is a wall or the goal, just ignore it
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal:
+                    #a full trail to the robot has been located, finished!
+                    minLoc = self.minSurroundingNodeValue(x, y)
+                    if minLoc < self.__reset_min and \
+                        self.__mapOfWorld[x][y] == self.__robot:
+                        if prnt:
+                            print("Finished Wavefront:\n")
+                            self.printMap()
+                        # Tell the robot to move after this return.
+                        return self.__min_node_location
+                    #record a value in to this node
+                    elif self.__minimum_node != self.__reset_min:
+                        #if this isnt here, 'nothing' will go in the location
+                        self.__mapOfWorld[x][y] = self.__minimum_node + 1
+                #go to next node and/or row
+                y += 1
+                if y == self.__width and x != self.__height:
+                    x += 1
+                    y = 0
+            #print self.__robot_x, self.__robot_y
+            if prnt:
+                print("Sweep #: %i\n" % (counter + 1))
+                self.printMap()
+            self.__steps += 1
+            counter += 1
+        return 0
+    ###########################################################################
+
+    def unpropagate(self):
+        """
+        clears old path to determine new path
+        stay within boundary
+
+        """
+
+        for x in range(0, self.__height):
+            for y in range(0, self.__width):
+                if self.__mapOfWorld[x][y] != self.__wall and \
+                    self.__mapOfWorld[x][y] != self.__goal and \
+                    self.__mapOfWorld[x][y] != self.__path:
+                    #if this location is a wall or goal, just ignore it
+                    self.__mapOfWorld[x][y] = self.__nothing #clear that space
+    ###########################################################################
+
+    def minSurroundingNodeValue(self, x, y):
+        """
+        this method looks at a node and returns the lowest value around that
+        node.
+
+        """
+
+        #reset minimum
+        self.__minimum_node = self.__reset_min
+        #down
+        if x < self.__height -1:
+            if self.__mapOfWorld[x + 1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x + 1][y] != self.__nothing:
+                #find the lowest number node, and exclude empty nodes (0's)
+                self.__minimum_node = self.__mapOfWorld[x + 1][y]
+                self.__min_node_location = 3
+        #up
+        if x > 0:
+            if self.__mapOfWorld[x-1][y] < self.__minimum_node and \
+                self.__mapOfWorld[x-1][y] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x-1][y]
+                self.__min_node_location = 1
+        #right
+        if y < self.__width -1:
+            if self.__mapOfWorld[x][y + 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y + 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y + 1]
+                self.__min_node_location = 2
+        #left
+        if y > 0:
+            if self.__mapOfWorld[x][y - 1] < self.__minimum_node and \
+                self.__mapOfWorld[x][y - 1] != self.__nothing:
+                self.__minimum_node = self.__mapOfWorld[x][y-1]
+                self.__min_node_location = 4
+        return self.__minimum_node
+    ###########################################################################
+
+    def printMap(self):
+        """
+        Prints out the map of this instance of the class.
+
+        """
+
+        msg = ''
+        for temp_B in range(0, self.__height):
+            for temp_A in range(0, self.__width):
+                if self.__mapOfWorld[temp_B][temp_A] == self.__wall:
+                    msg += "%04s" % "[#]"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__robot:
+                    msg += "%04s" % "-"
+                elif self.__mapOfWorld[temp_B][temp_A] == self.__goal:
+                    msg += "%04s" % "G"
+                else:
+                    msg += "%04s" % str(self.__mapOfWorld[temp_B][temp_A])
+            msg += "\n\n"
+        msg += "\n\n"
+        print(msg)
+        #
+        if self.__slow == True:
+            time.sleep(0.05)
+
+    def plotMap(self, img, path,mapWorldScaled,mapWorldOrg):
+        #Programm Koordinaten
+        imgTrans = cv2.transpose(img) # X und Y-Achse im Bild tauschen
+        imgPlot, ax0 = plt.subplots()
+        ax0.set_title('Programm Koordinaten')
+        ax0.imshow(imgTrans)
+        ax0.set_xlabel('[px]')
+        ax0.set_ylabel('[px]')
+        ax0.scatter(path[:,0], path[:,1], color='r')
+        #Karten Array Scaled
+        imgPlot1, ax1 = plt.subplots()
+        ax1.set_title('Karten-Array (Vergrößerte Hindernisse e=3)')
+        ax1.imshow(mapWorldScaled, cmap = 'Greys')
+        ax1.set_xlabel('[px]')
+        ax1.set_ylabel('[px]')
+        #Karten Array Normal
+        imgPlot2, ax2 = plt.subplots()
+        ax2.set_title('Karten-Array (Originale Hindernisse)')
+        ax2.imshow(mapWorldOrg, cmap = 'Greys')
+        ax2.set_xlabel('[px]')
+        ax2.set_ylabel('[px]')
+        #Bild Koordinaten
+        imgPlot3, ax3 = plt.subplots()
+        ax3.set_title('Bild Koordinaten')
+        ax3.set_xlabel('[px]')
+        ax3.set_ylabel('[px]')
+        ax3.imshow(img)
+        ax3.scatter(path[:,1], path[:,0], color='r')	
+        return
+
+    
+    def getPathWelt(self,path,height,Mapobj):   
+        pathWeltX, pathWeltY = Mapobj.calc_trans_welt(path[:,1], path[:,0], height)
+        pathEckenX = []
+        pathEckenY = []
+
+        for i,px in enumerate(pathWeltX):
+            if (i < len(pathWeltX)-1) & (i > 0):
+                if px != pathWeltX[i+1]:
+                    if pathWeltY[i]!=pathWeltY[i-1]:
+                        pathEckenX.append(px)
+                        pathEckenY.append(pathWeltY[i])
+                if pathWeltY[i] != pathWeltY[i+1]:
+                    if pathWeltX[i]!=pathWeltX[i-1]:
+                        pathEckenX.append(px)
+                        pathEckenY.append(pathWeltY[i])
+                        
+        pathEckenX.append(pathWeltX[-1])
+        pathEckenY.append(pathWeltY[-1])
+                        
+
+        uebergabePath = []
+        for i in range(0,len(pathEckenX)):
+            uebergabePath.append((pathEckenX[i],pathEckenY[i]))
+
+        print("Ecken: ", uebergabePath)
+
+        return uebergabePath
+
+############################################################################
+#%% Class Map
+class mapCreate:   
+    ############################################################################
+ 
+    def create_map(self, scale, cap):
+        img = cap.read()
+        
+        #Karte von Bild
+        #img = cv2.imread("D:/ros2_ws/src/sphero_mini_controller/sphero_mini_controller/map/map.jpg")
+        print('Original Dimensions : ',img.shape)
+        
+        scale_percent = 100-scale # percent of original size
+        width = int(img.shape[1] * scale_percent / 100)
+        height = int(img.shape[0] * scale_percent / 100)
+        dim = (width, height)
+
+        # resize image
+        resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
+        print('Resized Dimensions : ',resized.shape)
+
+        gray = cv2.cvtColor(resized, cv2.COLOR_RGB2GRAY)
+        mask = cv2.inRange(gray, np.array([200]), np.array([255])) #Parameter hängt von Umgebung ab
+
+        plt.plot(mask)
+
+        mapOfWorld = [[0]*gray.shape[1]]*gray.shape[0]
+        mask_list= np.ndarray.tolist(mask)
+
+        #Markiere alle leeren Zellen mit 000 und alle Zellen mit Hinderniss mit 999
+        for i in range(0,mask.shape[0]):
+            mapOfWorld[i] = ['999' if j > 200 else '000' for j in mask_list[i]]
+        
+        mapOfWorld = np.array(mapOfWorld, dtype = int)
+        mapOfWorldSized = mapOfWorld.copy()
+        
+        e = 3
+        #Hindernisse Größer machen
+        for i in range(0,mapOfWorld.shape[0]):
+            for j in range(0,mapOfWorld.shape[1]):
+                for r in range(0,e):
+                    try:
+                        if (mapOfWorldSized[i][j] == 999):
+                            mapOfWorld[i][j+e] = 999
+                            mapOfWorld[i+e][j] = 999
+                            mapOfWorld[i-e][j] = 999
+                            mapOfWorld[i][j-e] = 999
+                            mapOfWorld[i+e][j+e] = 999
+                            mapOfWorld[i+e][j-e] = 999
+                            mapOfWorld[i-e][j+e] = 999
+                            mapOfWorld[i-e][j-e] = 999
+                    except Exception:
+                        continue
+                    
+        return mapOfWorld, mapOfWorldSized
+    ############################################################################
+
+    def scale_koord(self, sx, sy, gx, gy,scale):
+        scale_percent = 100-scale # percent of original size
+
+        sx = int(sx*scale_percent/100)
+        sy = int(sy*scale_percent/100)
+        gx = int(gx*scale_percent/100)
+        gy = int(gy*scale_percent/100)
+        
+        return sx,sy,gx,gy
+    ############################################################################
+
+    def rescale_koord(self, path,scale):
+        scale_percent = 100-scale # percent of original size100
+
+        path = np.array(path)
+
+        for i in range(len(path)):
+            path[i] = path[i]*100/scale_percent
+
+        return path
+    ############################################################################
+
+    def calc_trans_welt(self, x, y, height):
+        yTrans = height - y
+        xTrans = x
+
+        return xTrans, yTrans
+###############################################################################
+#%% Main Funktion 
+def main(args = None):
+    #Verbindung herstellen, Node erstellen
+    try:
+        rclpy.init(args=args) #Kommunikation Starten
+        node = MyNode() #Node erstellen
+        sphero = node.connect()
+        thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
+        thread.start()
+
+    except Exception as e: # rclpy.ROSInterruptException
+        print("Konnte nicht verbinden")
+        raise e
+    
+    cap = VideoCapture("http://root:root@10.128.41.239:80/mjpg/video.mjpg")
+    #cap = VideoCapture(4)
+    Map = mapCreate()
+
+    img = cap.read()
+    height, width = img.shape[:2]
+
+    scale = 90
+
+    sphero.setLEDColor(255,0,0)
+    sphero.wait(1)
+    sphero.setBackLEDIntensity(0)
+    sphero.stabilization(True)
+
+    aOffset = node.calc_offset(sphero, cap, height) 
+
+    sphero.wait(1)
+
+    while(True):
+        mapWorldScaled, mapWorldOrg = Map.create_map(scale, cap)
+
+        #Befehle für WaveFrontPlanner/Maperstellung
+        sy,sx = node.get_pos(cap,height) #Aktuelle Roboter Pos in Welt
+        sy, sx = node.calc_trans(sy,sx,height)
+
+        gy = int(input("Bitte geben Sie die X-Zielkoordinate im Bild Koordinatensystem ein:"))    #X-Koordinate im Weltkoordinaten System
+        gx = int(input("Bitte geben Sie die Y-Zielkoordinate im Bild Koordinatensystem ein:"))    #Y-Koordinate im Weltkordinaten System
+        
+        sx,sy,gx,gy = Map.scale_koord(sx,sy,gx,gy,scale) #Kordinaten Tauschen X,Y
+
+        start = time.time()
+        planner = waveFrontPlanner(mapWorldScaled)
+        planner.setGoalPosition(gx,gy)
+        planner.setRobotPosition(sx,sy)
+        path = planner.run(False)
+        end = time.time()
+        print("Took %f seconds to run wavefront simulation" % (end - start))
+        
+        path = Map.rescale_koord(path, scale)
+        
+        planner.plotMap(img, path, mapWorldScaled, mapWorldOrg)
+
+        pathWelt = planner.getPathWelt(path, height, Map)
+
+        for p in pathWelt:
+            node.drive_to(sphero, p, aOffset, cap, height)
+            sphero.wait(1)
+
+        print("Geschafft")
+
+        if cv2.waitKey(10) & 0xFF == ord('q'):
+            break
+
+    rclpy.shutdown()
+
+############################################################################
+#%% Main
+if __name__ == '__main__':
+    main()
+############################################################################
diff --git a/ros2_ws/src/sphero_mini_controller/test/test_copyright.py b/ros2_ws/src/sphero_mini_controller/test/test_copyright.py
new file mode 100644
index 0000000..97a3919
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/test/test_copyright.py
@@ -0,0 +1,25 @@
+# Copyright 2015 Open Source Robotics Foundation, 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 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 ament_copyright.main import main
+import pytest
+
+
+# Remove the `skip` decorator once the source file(s) have a copyright header
+@pytest.mark.skip(reason='No copyright header has been placed in the generated source file.')
+@pytest.mark.copyright
+@pytest.mark.linter
+def test_copyright():
+    rc = main(argv=['.', 'test'])
+    assert rc == 0, 'Found errors'
diff --git a/ros2_ws/src/sphero_mini_controller/test/test_flake8.py b/ros2_ws/src/sphero_mini_controller/test/test_flake8.py
new file mode 100644
index 0000000..27ee107
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/test/test_flake8.py
@@ -0,0 +1,25 @@
+# Copyright 2017 Open Source Robotics Foundation, 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 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 ament_flake8.main import main_with_errors
+import pytest
+
+
+@pytest.mark.flake8
+@pytest.mark.linter
+def test_flake8():
+    rc, errors = main_with_errors(argv=[])
+    assert rc == 0, \
+        'Found %d code style errors / warnings:\n' % len(errors) + \
+        '\n'.join(errors)
diff --git a/ros2_ws/src/sphero_mini_controller/test/test_pep257.py b/ros2_ws/src/sphero_mini_controller/test/test_pep257.py
new file mode 100644
index 0000000..b234a38
--- /dev/null
+++ b/ros2_ws/src/sphero_mini_controller/test/test_pep257.py
@@ -0,0 +1,23 @@
+# Copyright 2015 Open Source Robotics Foundation, 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 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 ament_pep257.main import main
+import pytest
+
+
+@pytest.mark.linter
+@pytest.mark.pep257
+def test_pep257():
+    rc = main(argv=['.', 'test'])
+    assert rc == 0, 'Found code style errors / warnings'
-- 
GitLab