diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae32ee2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,118 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +.venv/ +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +.idea/ + +docs/.jekyll-cache/ + +.jekyll-cache +_site + +# IDEs +.vscode + +# jetbrains files +.idea/ + +# react stuff +node_modules/ + +lerna-debug.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +/.changelog +.npm/ +webpack-stats.json +*.DS_Store +react_frontend/static +developer_scripts +**.log \ No newline at end of file diff --git a/manager/__pycache__/__init__.cpython-38.pyc b/manager/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index cfba803..0000000 Binary files a/manager/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/comms/__pycache__/__init__.cpython-38.pyc b/manager/comms/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 34a664e..0000000 Binary files a/manager/comms/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/comms/__pycache__/new_consumer.cpython-38.pyc b/manager/comms/__pycache__/new_consumer.cpython-38.pyc deleted file mode 100644 index 051b777..0000000 Binary files a/manager/comms/__pycache__/new_consumer.cpython-38.pyc and /dev/null differ diff --git a/manager/libs/__pycache__/__init__.cpython-38.pyc b/manager/libs/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 1624a39..0000000 Binary files a/manager/libs/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/libs/__pycache__/process_utils.cpython-38.pyc b/manager/libs/__pycache__/process_utils.cpython-38.pyc deleted file mode 100644 index 9bfd109..0000000 Binary files a/manager/libs/__pycache__/process_utils.cpython-38.pyc and /dev/null differ diff --git a/manager/libs/applications/__pycache__/__init__.cpython-38.pyc b/manager/libs/applications/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index c271c72..0000000 Binary files a/manager/libs/applications/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/libs/applications/compatibility/__pycache__/__init__.cpython-38.pyc b/manager/libs/applications/compatibility/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index ca56f5f..0000000 Binary files a/manager/libs/applications/compatibility/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/libs/applications/compatibility/__pycache__/client.cpython-38.pyc b/manager/libs/applications/compatibility/__pycache__/client.cpython-38.pyc deleted file mode 100644 index 8bc1cf3..0000000 Binary files a/manager/libs/applications/compatibility/__pycache__/client.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/__pycache__/__init__.cpython-38.pyc b/manager/manager/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 2b7673c..0000000 Binary files a/manager/manager/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/application/__pycache__/__init__.cpython-38.pyc b/manager/manager/application/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index e283544..0000000 Binary files a/manager/manager/application/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/application/__pycache__/robotics_python_application_interface.cpython-38.pyc b/manager/manager/application/__pycache__/robotics_python_application_interface.cpython-38.pyc deleted file mode 100644 index ec5192c..0000000 Binary files a/manager/manager/application/__pycache__/robotics_python_application_interface.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/docker_thread/__pycache__/__init__.cpython-38.pyc b/manager/manager/docker_thread/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 889c53d..0000000 Binary files a/manager/manager/docker_thread/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/docker_thread/__pycache__/docker_thread.cpython-38.pyc b/manager/manager/docker_thread/__pycache__/docker_thread.cpython-38.pyc deleted file mode 100644 index 5609712..0000000 Binary files a/manager/manager/docker_thread/__pycache__/docker_thread.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/launcher/__pycache__/__init__.cpython-38.pyc b/manager/manager/launcher/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 81c6ebb..0000000 Binary files a/manager/manager/launcher/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/launcher/__pycache__/launcher_console.cpython-38.pyc b/manager/manager/launcher/__pycache__/launcher_console.cpython-38.pyc deleted file mode 100644 index 85c22bd..0000000 Binary files a/manager/manager/launcher/__pycache__/launcher_console.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/launcher/__pycache__/launcher_engine.cpython-38.pyc b/manager/manager/launcher/__pycache__/launcher_engine.cpython-38.pyc deleted file mode 100644 index eb8407d..0000000 Binary files a/manager/manager/launcher/__pycache__/launcher_engine.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/launcher/__pycache__/launcher_gazebo_view.cpython-38.pyc b/manager/manager/launcher/__pycache__/launcher_gazebo_view.cpython-38.pyc deleted file mode 100644 index 4c47e20..0000000 Binary files a/manager/manager/launcher/__pycache__/launcher_gazebo_view.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/launcher/__pycache__/launcher_ros_api.cpython-38.pyc b/manager/manager/launcher/__pycache__/launcher_ros_api.cpython-38.pyc deleted file mode 100644 index 419a2b0..0000000 Binary files a/manager/manager/launcher/__pycache__/launcher_ros_api.cpython-38.pyc and /dev/null differ diff --git a/manager/manager/lint/__pycache__/__init__.cpython-38.pyc b/manager/manager/lint/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index d633941..0000000 Binary files a/manager/manager/lint/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/ram_logging/__pycache__/__init__.cpython-38.pyc b/manager/ram_logging/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 03e36e7..0000000 Binary files a/manager/ram_logging/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/manager/__init__.py b/src/__init__.py similarity index 100% rename from manager/__init__.py rename to src/__init__.py diff --git a/src/__pycache__/__init__.cpython-38.pyc b/src/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..e8f374a Binary files /dev/null and b/src/__pycache__/__init__.cpython-38.pyc differ diff --git a/manager/comms/__init__.py b/src/comms/__init__.py similarity index 100% rename from manager/comms/__init__.py rename to src/comms/__init__.py diff --git a/src/comms/__pycache__/__init__.cpython-38.pyc b/src/comms/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..2461863 Binary files /dev/null and b/src/comms/__pycache__/__init__.cpython-38.pyc differ diff --git a/manager/comms/__pycache__/consumer_message.cpython-38.pyc b/src/comms/__pycache__/consumer_message.cpython-38.pyc similarity index 79% rename from manager/comms/__pycache__/consumer_message.cpython-38.pyc rename to src/comms/__pycache__/consumer_message.cpython-38.pyc index 63485c6..ee88410 100644 Binary files a/manager/comms/__pycache__/consumer_message.cpython-38.pyc and b/src/comms/__pycache__/consumer_message.cpython-38.pyc differ diff --git a/src/comms/__pycache__/new_consumer.cpython-38.pyc b/src/comms/__pycache__/new_consumer.cpython-38.pyc new file mode 100644 index 0000000..5af0880 Binary files /dev/null and b/src/comms/__pycache__/new_consumer.cpython-38.pyc differ diff --git a/manager/comms/consumer.py b/src/comms/consumer.py similarity index 93% rename from manager/comms/consumer.py rename to src/comms/consumer.py index 67021f0..16147f3 100644 --- a/manager/comms/consumer.py +++ b/src/comms/consumer.py @@ -6,8 +6,8 @@ import websockets from websockets.server import WebSocketServerProtocol -from src.manager.comms.consumer_message import ManagerConsumerMessage, ManagerConsumerMessageException -from src.manager.ram_logging.log_manager import LogManager +from .consumer_message import ManagerConsumerMessage, ManagerConsumerMessageException +from ..ram_logging.log_manager import LogManager logger = LogManager.logger @@ -17,9 +17,7 @@ class ManagerConsumer: """ def __init__(self, host, port): - from src.manager.manager import Manager - - + from ..manager.manager import Manager """ Initializes a new ManagerConsumer @param host: host for connections, '0.0.0.0' to bind all interfaces diff --git a/manager/comms/consumer_message.py b/src/comms/consumer_message.py similarity index 100% rename from manager/comms/consumer_message.py rename to src/comms/consumer_message.py diff --git a/manager/comms/new_consumer.py b/src/comms/new_consumer.py similarity index 92% rename from manager/comms/new_consumer.py rename to src/comms/new_consumer.py index 26f1763..753961c 100644 --- a/manager/comms/new_consumer.py +++ b/src/comms/new_consumer.py @@ -5,8 +5,8 @@ from websocket_server import WebsocketServer from datetime import datetime -from src.manager.comms.consumer_message import ManagerConsumerMessageException, ManagerConsumerMessage -from src.manager.ram_logging.log_manager import LogManager +from .consumer_message import ManagerConsumerMessageException, ManagerConsumerMessage +from ..ram_logging.log_manager import LogManager class Client: @@ -42,9 +42,12 @@ def handle_client_disconnect(self, client, server): if client is None: return LogManager.logger.info(f"client disconnected: {client}") + + # TODO: remove print now = datetime.now() time_string = now.strftime("%H:%M:%S") - print(time_string) + print(f"client disconnected: {client} at {time_string}") + message = ManagerConsumerMessage(**{'id': str(uuid4()), 'command': 'disconnect'}) self.manager_queue.put(message) self.client = None diff --git a/manager/libs/__init__.py b/src/libs/__init__.py similarity index 100% rename from manager/libs/__init__.py rename to src/libs/__init__.py diff --git a/src/libs/__pycache__/__init__.cpython-38.pyc b/src/libs/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..d1a5d4f Binary files /dev/null and b/src/libs/__pycache__/__init__.cpython-38.pyc differ diff --git a/src/libs/__pycache__/process_utils.cpython-38.pyc b/src/libs/__pycache__/process_utils.cpython-38.pyc new file mode 100644 index 0000000..3269aab Binary files /dev/null and b/src/libs/__pycache__/process_utils.cpython-38.pyc differ diff --git a/manager/libs/applications/__init__.py b/src/libs/applications/__init__.py similarity index 100% rename from manager/libs/applications/__init__.py rename to src/libs/applications/__init__.py diff --git a/src/libs/applications/__pycache__/__init__.cpython-38.pyc b/src/libs/applications/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..2605f1a Binary files /dev/null and b/src/libs/applications/__pycache__/__init__.cpython-38.pyc differ diff --git a/manager/libs/applications/brain_exercise.py b/src/libs/applications/brain_exercise.py similarity index 54% rename from manager/libs/applications/brain_exercise.py rename to src/libs/applications/brain_exercise.py index 4f0636d..d1179f7 100644 --- a/manager/libs/applications/brain_exercise.py +++ b/src/libs/applications/brain_exercise.py @@ -1,7 +1,16 @@ -from src.manager.application.robotics_python_application_interface import IRoboticsPythonApplication +from ...manager.application.robotics_python_application_interface import IRoboticsPythonApplication class BrainExercise(IRoboticsPythonApplication): + def pause(self): + pass + + def resume(self): + pass + + def terminate(self): + pass + def load_code(self, code: str): pass diff --git a/manager/libs/applications/compatibility/__init__.py b/src/libs/applications/compatibility/__init__.py similarity index 100% rename from manager/libs/applications/compatibility/__init__.py rename to src/libs/applications/compatibility/__init__.py diff --git a/src/libs/applications/compatibility/__pycache__/__init__.cpython-38.pyc b/src/libs/applications/compatibility/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..7104813 Binary files /dev/null and b/src/libs/applications/compatibility/__pycache__/__init__.cpython-38.pyc differ diff --git a/src/libs/applications/compatibility/__pycache__/client.cpython-38.pyc b/src/libs/applications/compatibility/__pycache__/client.cpython-38.pyc new file mode 100644 index 0000000..a98e618 Binary files /dev/null and b/src/libs/applications/compatibility/__pycache__/client.cpython-38.pyc differ diff --git a/manager/libs/applications/compatibility/__pycache__/exercise_wrapper.cpython-38.pyc b/src/libs/applications/compatibility/__pycache__/exercise_wrapper.cpython-38.pyc similarity index 52% rename from manager/libs/applications/compatibility/__pycache__/exercise_wrapper.cpython-38.pyc rename to src/libs/applications/compatibility/__pycache__/exercise_wrapper.cpython-38.pyc index ab943e4..3390dac 100644 Binary files a/manager/libs/applications/compatibility/__pycache__/exercise_wrapper.cpython-38.pyc and b/src/libs/applications/compatibility/__pycache__/exercise_wrapper.cpython-38.pyc differ diff --git a/manager/libs/applications/compatibility/client.py b/src/libs/applications/compatibility/client.py similarity index 90% rename from manager/libs/applications/compatibility/client.py rename to src/libs/applications/compatibility/client.py index 818aa6c..432a785 100644 --- a/manager/libs/applications/compatibility/client.py +++ b/src/libs/applications/compatibility/client.py @@ -1,7 +1,7 @@ import threading import websocket -from src.manager.ram_logging.log_manager import LogManager +from ....ram_logging.log_manager import LogManager class Client(threading.Thread): @@ -37,6 +37,7 @@ def on_message(self, ws, message): self.callback(self.name, message) def on_error(self, ws, error): + LogManager.logger.info(f"There was an error in {self.name} client connection.") LogManager.logger.error(error) def on_close(self, ws, status, msg): diff --git a/manager/libs/applications/compatibility/exercise_wrapper.py b/src/libs/applications/compatibility/exercise_wrapper.py similarity index 87% rename from manager/libs/applications/compatibility/exercise_wrapper.py rename to src/libs/applications/compatibility/exercise_wrapper.py index 1bcf565..6af3519 100644 --- a/manager/libs/applications/compatibility/exercise_wrapper.py +++ b/src/libs/applications/compatibility/exercise_wrapper.py @@ -8,11 +8,11 @@ import rosservice from threading import Thread -from src.manager.libs.applications.compatibility.client import Client -from src.manager.libs.process_utils import stop_process_and_children -from src.manager.ram_logging.log_manager import LogManager -from src.manager.manager.application.robotics_python_application_interface import IRoboticsPythonApplication -from src.manager.manager.lint.linter import Lint +from ...applications.compatibility.client import Client +from ...process_utils import stop_process_and_children +from ....ram_logging.log_manager import LogManager +from ....manager.application.robotics_python_application_interface import IRoboticsPythonApplication +from ....manager.lint.linter import Lint class CompatibilityExerciseWrapper(IRoboticsPythonApplication): @@ -28,11 +28,9 @@ def __init__(self, exercise_command, gui_command, update_callback): f'{home_dir}/ws_code.log', 'websocket_code=ready') if process_ready: - LogManager.logger.info( - f"Exercise code {exercise_command} launched") + LogManager.logger.info(f"Exercise code {exercise_command} launched") time.sleep(1) - self.exercise_connection = Client( - 'ws://127.0.0.1:1905', 'exercise', self.server_message) + self.exercise_connection = Client('ws://127.0.0.1:1905', 'exercise', self.server_message) self.exercise_connection.start() else: self.exercise_server.kill() @@ -43,18 +41,16 @@ def __init__(self, exercise_command, gui_command, update_callback): if process_ready: LogManager.logger.info(f"Exercise gui {gui_command} launched") time.sleep(1) - self.gui_connection = Client( - 'ws://127.0.0.1:2303', 'gui', self.server_message) + self.gui_connection = Client('ws://127.0.0.1:2303', 'gui', self.server_message) self.gui_connection.start() else: self.gui_server.kill() raise RuntimeError(f"Exercise GUI {gui_command} could not be run") - + self.running = True self.start_send_freq_thread() - def send_freq(self, exercise_connection, is_alive): """Send the frequency of the brain and gui to the exercise server""" while is_alive(): diff --git a/manager/libs/applications/compatibility/robotics_application_wrapper.py b/src/libs/applications/compatibility/robotics_application_wrapper.py similarity index 67% rename from manager/libs/applications/compatibility/robotics_application_wrapper.py rename to src/libs/applications/compatibility/robotics_application_wrapper.py index 60e2d10..16a95cf 100644 --- a/manager/libs/applications/compatibility/robotics_application_wrapper.py +++ b/src/libs/applications/compatibility/robotics_application_wrapper.py @@ -5,19 +5,13 @@ import psutil -from src.manager.libs.process_utils import stop_process_and_children -from src.manager.manager.application.robotics_python_application_interface import IRoboticsPythonApplication -from src.manager.manager.lint.linter import Lint -from src.manager.manager.docker_thread.docker_thread import DockerThread - -from src.manager.libs.applications.compatibility.client import Client -from src.manager.libs.process_utils import stop_process_and_children -from src.manager.ram_logging.log_manager import LogManager -from src.manager.manager.application.robotics_python_application_interface import IRoboticsPythonApplication -from src.manager.manager.lint.linter import Lint +from ...process_utils import stop_process_and_children +from ....manager.application.robotics_python_application_interface import IRoboticsPythonApplication +from ....manager.lint.linter import Lint import os + class RoboticsApplicationWrapper(IRoboticsPythonApplication): def __init__(self, update_callback): @@ -29,8 +23,9 @@ def __init__(self, update_callback): self.user_process = None def _create_process(self, cmd): - #print("creando procesos") - process = subprocess.Popen(f"{cmd}", shell=True, stdout = sys.stdout, stderr=subprocess.STDOUT, bufsize=1024, universal_newlines=True) + # print("creando procesos") + process = subprocess.Popen(f"{cmd}", shell=True, stdout=sys.stdout, stderr=subprocess.STDOUT, bufsize=1024, + universal_newlines=True) psProcess = psutil.Process(pid=process.pid) return psProcess @@ -44,9 +39,9 @@ def load_code(self, code: str): self.f = open("user_code.py", "w") self.f.write(code) self.f.close() - #self.update_callback("Hello World") + # self.update_callback("Hello World") - def run(self): + def run(self): self.user_process = self._create_process(f"DISPLAY=:2 python {self.f.name}") self.running = True @@ -92,9 +87,9 @@ def suspend_resume(self, signal): # send signal to processes for p in children: try: - if(signal == "pause"): + if (signal == "pause"): p.suspend() - if(signal == "resume"): + if (signal == "resume"): p.resume() except psutil.NoSuchProcess: - pass \ No newline at end of file + pass diff --git a/manager/libs/applications/robotics_application.py b/src/libs/applications/robotics_application.py similarity index 63% rename from manager/libs/applications/robotics_application.py rename to src/libs/applications/robotics_application.py index 3c6b2cd..b201ee1 100644 --- a/manager/libs/applications/robotics_application.py +++ b/src/libs/applications/robotics_application.py @@ -1,7 +1,13 @@ -from src.manager.manager.application.robotics_python_application_interface import IRoboticsPythonApplication +from ...manager.application.robotics_python_application_interface import IRoboticsPythonApplication class RoboticsApplication(IRoboticsPythonApplication): + def pause(self): + pass + + def resume(self): + pass + def terminate(self): pass diff --git a/manager/libs/process_utils.py b/src/libs/process_utils.py similarity index 58% rename from manager/libs/process_utils.py rename to src/libs/process_utils.py index 96c952a..8226f7d 100644 --- a/manager/libs/process_utils.py +++ b/src/libs/process_utils.py @@ -1,7 +1,4 @@ -# Thanks to https://stackoverflow.com/questions/452969/does-python-have-an-equivalent-to-java-class-forname -# This should be moved to a utils library import importlib.util -import os.path import sys from subprocess import Popen @@ -17,6 +14,8 @@ def get_class(kls): return m +# Thanks to https://stackoverflow.com/questions/452969/does-python-have-an-equivalent-to-java-class-forname +# This should be moved to a utils library def get_class_from_file(file_path: str, class_name: str): spec = importlib.util.spec_from_file_location("application", file_path) module = importlib.util.module_from_spec(spec) @@ -33,33 +32,47 @@ def class_from_module(module: str): def stop_process_and_children(process: Popen, signal: int = 9, timeout: int = None): + # from ..ram_logging.log_manager import LogManager """ Stops a list of processes waiting for them to stop """ - # collect processes to stop - proc = psutil.Process(process.pid) - children = proc.children(recursive=True) - children.append(proc) + try: + # collect processes to stop + proc = psutil.Process(process.pid) + name = proc.name() + children = proc.children(recursive=True) + children.append(proc) - # send signal to processes - for p in children: - try: - p.send_signal(signal) - except psutil.NoSuchProcess: - pass + # send signal to processes + for p in children: + try: + p.send_signal(signal) + except psutil.NoSuchProcess: + pass - gone, alive = psutil.wait_procs(children, timeout=timeout) - return gone, alive + gone, alive = psutil.wait_procs(children, timeout=timeout) + # TODO: log + # LogManager.logger.info(f"Process {name} and it's children were stopped") + print(f"Process {name} and it's children were stopped") + + return gone, alive + except psutil.NoSuchProcess: + # TODO: log + # LogManager.logger.info(f"Process with pid {process.pid} is already closed") + print(f"Process with pid {process.pid} is already closed") class classproperty(property): def __get__(self, cls, owner): return classmethod(self.fget).__get__(None, owner)() + def singleton(cls): instances = {} + def get_instance(): if cls not in instances: instances[cls] = cls() return instances[cls] - return get_instance() \ No newline at end of file + + return get_instance() diff --git a/manager/manager/__init__.py b/src/manager/__init__.py similarity index 100% rename from manager/manager/__init__.py rename to src/manager/__init__.py diff --git a/src/manager/__pycache__/__init__.cpython-38.pyc b/src/manager/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..19faf71 Binary files /dev/null and b/src/manager/__pycache__/__init__.cpython-38.pyc differ diff --git a/src/manager/__pycache__/manager.cpython-38.pyc b/src/manager/__pycache__/manager.cpython-38.pyc new file mode 100644 index 0000000..9b39c51 Binary files /dev/null and b/src/manager/__pycache__/manager.cpython-38.pyc differ diff --git a/manager/manager/application/__init__.py b/src/manager/application/__init__.py similarity index 100% rename from manager/manager/application/__init__.py rename to src/manager/application/__init__.py diff --git a/src/manager/application/__pycache__/__init__.cpython-38.pyc b/src/manager/application/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..01ca6f8 Binary files /dev/null and b/src/manager/application/__pycache__/__init__.cpython-38.pyc differ diff --git a/src/manager/application/__pycache__/robotics_python_application_interface.cpython-38.pyc b/src/manager/application/__pycache__/robotics_python_application_interface.cpython-38.pyc new file mode 100644 index 0000000..282f3f1 Binary files /dev/null and b/src/manager/application/__pycache__/robotics_python_application_interface.cpython-38.pyc differ diff --git a/manager/manager/application/robotics_python_application_interface.py b/src/manager/application/robotics_python_application_interface.py similarity index 100% rename from manager/manager/application/robotics_python_application_interface.py rename to src/manager/application/robotics_python_application_interface.py diff --git a/manager/manager/config.json b/src/manager/config.json similarity index 100% rename from manager/manager/config.json rename to src/manager/config.json diff --git a/manager/manager/docker_thread/__init__.py b/src/manager/docker_thread/__init__.py similarity index 100% rename from manager/manager/docker_thread/__init__.py rename to src/manager/docker_thread/__init__.py diff --git a/manager/manager/docker_thread/docker_thread.py b/src/manager/docker_thread/docker_thread.py similarity index 76% rename from manager/manager/docker_thread/docker_thread.py rename to src/manager/docker_thread/docker_thread.py index d84dff1..78bd739 100644 --- a/manager/manager/docker_thread/docker_thread.py +++ b/src/manager/docker_thread/docker_thread.py @@ -5,19 +5,19 @@ import signal - - class DockerThread(threading.Thread): """Threaded Docker Thread Class""" + def __init__(self, cmd, shell=True): threading.Thread.__init__(self) self.cmd = cmd self.process = None - self.shell=shell + self.shell = shell def run(self): - self.process = subprocess.Popen(self.cmd, shell=self.shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True, - bufsize=1024, universal_newlines=True) + self.process = subprocess.Popen(self.cmd, shell=self.shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + start_new_session=True, + bufsize=1024, universal_newlines=True) self.process.communicate() def terminate(self): @@ -27,4 +27,3 @@ def terminate(self): os.killpg(os.getpgid(self.process.pid), signal.SIGTERM) except ProcessLookupError as error: print(f"{self.process.pid}: Process already terminated {error}") - \ No newline at end of file diff --git a/manager/manager/launcher/__init__.py b/src/manager/launcher/__init__.py similarity index 100% rename from manager/manager/launcher/__init__.py rename to src/manager/launcher/__init__.py diff --git a/src/manager/launcher/__pycache__/__init__.cpython-38.pyc b/src/manager/launcher/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..6fac8a3 Binary files /dev/null and b/src/manager/launcher/__pycache__/__init__.cpython-38.pyc differ diff --git a/src/manager/launcher/__pycache__/launcher_engine.cpython-38.pyc b/src/manager/launcher/__pycache__/launcher_engine.cpython-38.pyc new file mode 100644 index 0000000..e7d5b39 Binary files /dev/null and b/src/manager/launcher/__pycache__/launcher_engine.cpython-38.pyc differ diff --git a/manager/manager/launcher/__pycache__/launcher_interface.cpython-38.pyc b/src/manager/launcher/__pycache__/launcher_interface.cpython-38.pyc similarity index 82% rename from manager/manager/launcher/__pycache__/launcher_interface.cpython-38.pyc rename to src/manager/launcher/__pycache__/launcher_interface.cpython-38.pyc index 5ea05fb..d6a9761 100644 Binary files a/manager/manager/launcher/__pycache__/launcher_interface.cpython-38.pyc and b/src/manager/launcher/__pycache__/launcher_interface.cpython-38.pyc differ diff --git a/src/manager/launcher/__pycache__/launcher_ros_api.cpython-38.pyc b/src/manager/launcher/__pycache__/launcher_ros_api.cpython-38.pyc new file mode 100644 index 0000000..c3a5ba1 Binary files /dev/null and b/src/manager/launcher/__pycache__/launcher_ros_api.cpython-38.pyc differ diff --git a/manager/manager/launcher/launcher_console.py b/src/manager/launcher/launcher_console.py similarity index 92% rename from manager/manager/launcher/launcher_console.py rename to src/manager/launcher/launcher_console.py index 606b7f0..f2c576e 100644 --- a/manager/manager/launcher/launcher_console.py +++ b/src/manager/launcher/launcher_console.py @@ -1,8 +1,7 @@ """Launcher for Console""""" import time -from src.manager.manager.launcher.launcher_interface import ILauncher -from src.manager.manager.docker_thread.docker_thread import DockerThread - +from .launcher_interface import ILauncher +from ..docker_thread.docker_thread import DockerThread class LauncherConsole(ILauncher): diff --git a/manager/manager/launcher/launcher_engine.py b/src/manager/launcher/launcher_engine.py similarity index 94% rename from manager/manager/launcher/launcher_engine.py rename to src/manager/launcher/launcher_engine.py index a435ec9..5a8ac11 100644 --- a/manager/manager/launcher/launcher_engine.py +++ b/src/manager/launcher/launcher_engine.py @@ -2,8 +2,8 @@ from pydantic import BaseModel -from src.manager.libs.process_utils import get_class, class_from_module -from src.manager.ram_logging.log_manager import LogManager +from ...libs.process_utils import get_class, class_from_module +from ...ram_logging.log_manager import LogManager class LauncherEngine(BaseModel): diff --git a/manager/manager/launcher/launcher_gazebo_view.py b/src/manager/launcher/launcher_gazebo_view.py similarity index 93% rename from manager/manager/launcher/launcher_gazebo_view.py rename to src/manager/launcher/launcher_gazebo_view.py index 5bf567d..4c2fc6f 100644 --- a/manager/manager/launcher/launcher_gazebo_view.py +++ b/src/manager/launcher/launcher_gazebo_view.py @@ -1,8 +1,7 @@ """Launcher for Gazebo View""""" import time -from src.manager.manager.launcher.launcher_interface import ILauncher -from src.manager.manager.docker_thread.docker_thread import DockerThread - +from .launcher_interface import ILauncher +from ..docker_thread.docker_thread import DockerThread class LauncherGazeboView(ILauncher): diff --git a/manager/manager/launcher/launcher_interface.py b/src/manager/launcher/launcher_interface.py similarity index 100% rename from manager/manager/launcher/launcher_interface.py rename to src/manager/launcher/launcher_interface.py diff --git a/manager/manager/launcher/launcher_robot_display_view.py b/src/manager/launcher/launcher_robot_display_view.py similarity index 90% rename from manager/manager/launcher/launcher_robot_display_view.py rename to src/manager/launcher/launcher_robot_display_view.py index afa5e8e..45c8c75 100644 --- a/manager/manager/launcher/launcher_robot_display_view.py +++ b/src/manager/launcher/launcher_robot_display_view.py @@ -1,5 +1,5 @@ -from src.manager.manager.launcher.launcher_interface import ILauncher -from src.manager.manager.docker_thread.docker_thread import DockerThread +from .launcher_interface import ILauncher +from ..docker_thread.docker_thread import DockerThread import time diff --git a/manager/manager/launcher/launcher_ros.py b/src/manager/launcher/launcher_ros.py similarity index 97% rename from manager/manager/launcher/launcher_ros.py rename to src/manager/launcher/launcher_ros.py index 5063199..24a0c93 100644 --- a/manager/manager/launcher/launcher_ros.py +++ b/src/manager/launcher/launcher_ros.py @@ -4,7 +4,7 @@ import traceback from typing import Any, List -from src.manager.launcher.launcher_interface import ILauncher, LauncherException +from .launcher_interface import ILauncher, LauncherException class LauncherRos(ILauncher): diff --git a/manager/manager/launcher/launcher_ros_api.py b/src/manager/launcher/launcher_ros_api.py similarity index 96% rename from manager/manager/launcher/launcher_ros_api.py rename to src/manager/launcher/launcher_ros_api.py index 0a3b0c8..f5526fa 100644 --- a/manager/manager/launcher/launcher_ros_api.py +++ b/src/manager/launcher/launcher_ros_api.py @@ -1,10 +1,9 @@ import os -import time from typing import List, Any import roslaunch import rospy -from src.manager.manager.launcher.launcher_interface import ILauncher, LauncherException +from .launcher_interface import ILauncher, LauncherException import logging diff --git a/manager/manager/lint/__init__.py b/src/manager/lint/__init__.py similarity index 100% rename from manager/manager/lint/__init__.py rename to src/manager/lint/__init__.py diff --git a/src/manager/lint/__pycache__/__init__.cpython-38.pyc b/src/manager/lint/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..ceab6d5 Binary files /dev/null and b/src/manager/lint/__pycache__/__init__.cpython-38.pyc differ diff --git a/manager/manager/lint/__pycache__/linter.cpython-38.pyc b/src/manager/lint/__pycache__/linter.cpython-38.pyc similarity index 78% rename from manager/manager/lint/__pycache__/linter.cpython-38.pyc rename to src/manager/lint/__pycache__/linter.cpython-38.pyc index 0e92ef7..e806f28 100644 Binary files a/manager/manager/lint/__pycache__/linter.cpython-38.pyc and b/src/manager/lint/__pycache__/linter.cpython-38.pyc differ diff --git a/manager/manager/lint/linter.py b/src/manager/lint/linter.py similarity index 88% rename from manager/manager/lint/linter.py rename to src/manager/lint/linter.py index 95a96b0..e0d628e 100644 --- a/manager/manager/lint/linter.py +++ b/src/manager/lint/linter.py @@ -3,7 +3,6 @@ class Lint: - def evaluate_code(self, code, warnings=False): try: code = re.sub(r'from HAL import HAL', 'from hal import HAL', code) @@ -13,11 +12,13 @@ def evaluate_code(self, code, warnings=False): # Avoids EOF error when iterative code is empty (which prevents other errors from showing) while_position = re.search( - r'[^ ]while\s*\(\s*True\s*\)\s*:|[^ ]while\s*True\s*:|[^ ]while\s*1\s*:|[^ ]while\s*\(\s*1\s*\)\s*:', code) + r'[^ ]while\s*\(\s*True\s*\)\s*:|[^ ]while\s*True\s*:|[^ ]while\s*1\s*:|[^ ]while\s*\(\s*1\s*\)\s*:', + code) sequential_code = code[:while_position.start()] iterative_code = code[while_position.start():] iterative_code = re.sub( - r'[^ ]while\s*\(\s*True\s*\)\s*:|[^ ]while\s*True\s*:|[^ ]while\s*1\s*:|[^ ]while\s*\(\s*1\s*\)\s*:', '\n', iterative_code, 1) + r'[^ ]while\s*\(\s*True\s*\)\s*:|[^ ]while\s*True\s*:|[^ ]while\s*1\s*:|[^ ]while\s*\(\s*1\s*\)\s*:', + '\n', iterative_code, 1) iterative_code = re.sub(r'^[ ]{4}', '', iterative_code, flags=re.M) code = sequential_code + iterative_code @@ -44,13 +45,13 @@ def evaluate_code(self, code, warnings=False): warning_messages = re.search(":[0-9]+: warning.*\n", result) while (warning_messages != None): result = result[:warning_messages.start()] + \ - result[warning_messages.end():] + result[warning_messages.end():] warning_messages = re.search( ":[0-9]+: warning.*\n", result) refactor_messages = re.search(":[0-9]+: refactor.*\n", result) while (refactor_messages != None): result = result[:refactor_messages.start()] + \ - result[refactor_messages.end():] + result[refactor_messages.end():] refactor_messages = re.search( ":[0-9]+: refactor.*\n", result) @@ -58,14 +59,14 @@ def evaluate_code(self, code, warnings=False): eof_exception = re.search(":[0-9]+: error.*EOF.*\n", result) if (eof_exception != None): result = result[:eof_exception.start()] + \ - result[eof_exception.end():] + result[eof_exception.end():] # Removes no value for argument 'self' error self_exception = re.search( ":[0-9]+:.*value.*argument.*unbound.*method.*\n", result) while (self_exception != None): result = result[:self_exception.start()] + \ - result[self_exception.end():] + result[self_exception.end():] self_exception = re.search( ":[0-9]+:.*value.*argument.*unbound.*method.*\n", result) @@ -73,14 +74,14 @@ def evaluate_code(self, code, warnings=False): self_exception = re.search(":[0-9]+:.*E1111.*\n", result) while (self_exception != None): result = result[:self_exception.start()] + \ - result[self_exception.end():] + result[self_exception.end():] self_exception = re.search(":[0-9]+:.*E1111.*\n", result) # Removes E1136 until issue https://github.com/PyCQA/pylint/issues/1498 is closed self_exception = re.search(":[0-9]+:.*E1136.*\n", result) while (self_exception != None): result = result[:self_exception.start()] + \ - result[self_exception.end():] + result[self_exception.end():] self_exception = re.search(":[0-9]+:.*E1136.*\n", result) # Returns an empty string if there are no errors diff --git a/manager/manager/lint/pylint_checker.py b/src/manager/lint/pylint_checker.py similarity index 99% rename from manager/manager/lint/pylint_checker.py rename to src/manager/lint/pylint_checker.py index d55ce9a..666f726 100644 --- a/manager/manager/lint/pylint_checker.py +++ b/src/manager/lint/pylint_checker.py @@ -1,7 +1,6 @@ import tempfile from pylint import epylint as lint - code = open('user_code.py') python_code = code.read() code.close() diff --git a/manager/manager/manager.py b/src/manager/manager.py similarity index 88% rename from manager/manager/manager.py rename to src/manager/manager.py index a631ca4..b604ca2 100644 --- a/manager/manager/manager.py +++ b/src/manager/manager.py @@ -9,18 +9,12 @@ from queue import Queue from uuid import uuid4 - - -from src.manager.manager.launcher.launcher_engine import LauncherEngine -from src.manager.manager.application.robotics_python_application_interface import IRoboticsPythonApplication -from src.manager.libs.process_utils import get_class_from_file -from src.manager.comms.consumer_message import ManagerConsumerMessageException -from src.manager.ram_logging.log_manager import LogManager -from src.manager.comms.new_consumer import ManagerConsumer - - - - +from .launcher.launcher_engine import LauncherEngine +from .application.robotics_python_application_interface import IRoboticsPythonApplication +from ..libs.process_utils import get_class_from_file +from ..comms.consumer_message import ManagerConsumerMessageException +from ..ram_logging.log_manager import LogManager +from ..comms.new_consumer import ManagerConsumer # pylint: disable=unused-argument @@ -40,23 +34,23 @@ class Manager: {'trigger': 'connect', 'source': 'idle', 'dest': 'connected', 'before': 'on_connect'}, # Transitions for state connected {'trigger': 'launch', 'source': 'connected', - 'dest': 'ready', 'before': 'on_launch'}, + 'dest': 'ready', 'before': 'on_launch'}, # Transitions for state ready {'trigger': 'terminate', 'source': 'ready', - 'dest': 'connected', 'before': 'on_terminate'}, + 'dest': 'connected', 'before': 'on_terminate'}, {'trigger': 'load', 'source': [ 'ready', 'running', 'paused'], 'dest': 'ready', 'before': 'load_code'}, {'trigger': 'run', 'source': [ 'ready', 'paused'], 'dest': 'running', 'conditions': 'code_loaded', 'after': 'on_run'}, # Transitions for state running {'trigger': 'pause', 'source': 'running', - 'dest': 'paused', 'before': 'on_pause'}, + 'dest': 'paused', 'before': 'on_pause'}, {'trigger': 'stop', 'source': [ 'running', 'paused'], 'dest': 'ready', 'before': 'on_stop'}, # Global transitions {'trigger': 'disconnect', 'source': '*', - 'dest': 'idle', 'before': 'on_disconnect'}, - #{'trigger': 'get_state', 'source': '*', 'dest': '='}, + 'dest': 'idle', 'before': 'on_disconnect'}, + # {'trigger': 'get_state', 'source': '*', 'dest': '='}, ] @@ -96,6 +90,7 @@ def on_launch(self, event): """ Transition executed on launch trigger activ """ + def terminated_callback(name, code): # TODO: Prototype, review this callback LogManager.logger.info( @@ -161,8 +156,8 @@ def on_disconnect(self, event): except Exception as e: LogManager.logger.exception(f"Exception terminating instance") print(traceback.format_exc()) - python = sys.executable - os.execl(python, python, *sys.argv) + # python = sys.executable + # os.execl(python, python, *sys.argv) def on_enter_connected(self, event): LogManager.logger.info("Connect state entered") @@ -207,13 +202,13 @@ def start(self): f"Starting RAM consumer in {self.consumer.server}:{self.consumer.port}") self.consumer.start() - + def signal_handler(sign, frame): - print("\nprogram exiting gracefully") - self.running = False - self.application.terminate() - self.__code_loaded = False - self.launcher.terminate() + print("\nprogram exiting gracefully") + self.running = False + self.application.terminate() + self.__code_loaded = False + self.launcher.terminate() signal.signal(signal.SIGINT, signal_handler) @@ -238,6 +233,7 @@ def signal_handler(sign, frame): if __name__ == "__main__": import argparse + parser = argparse.ArgumentParser() parser.add_argument( "host", type=str, help="Host to listen to (0.0.0.0 or all hosts)") diff --git a/manager/ram_logging/__init__.py b/src/ram_logging/__init__.py similarity index 100% rename from manager/ram_logging/__init__.py rename to src/ram_logging/__init__.py diff --git a/src/ram_logging/__pycache__/__init__.cpython-38.pyc b/src/ram_logging/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..6ccf0e3 Binary files /dev/null and b/src/ram_logging/__pycache__/__init__.cpython-38.pyc differ diff --git a/manager/ram_logging/__pycache__/log_manager.cpython-38.pyc b/src/ram_logging/__pycache__/log_manager.cpython-38.pyc similarity index 59% rename from manager/ram_logging/__pycache__/log_manager.cpython-38.pyc rename to src/ram_logging/__pycache__/log_manager.cpython-38.pyc index 90257aa..68dceed 100644 Binary files a/manager/ram_logging/__pycache__/log_manager.cpython-38.pyc and b/src/ram_logging/__pycache__/log_manager.cpython-38.pyc differ diff --git a/manager/ram_logging/log_manager.py b/src/ram_logging/log_manager.py similarity index 92% rename from manager/ram_logging/log_manager.py rename to src/ram_logging/log_manager.py index f933d67..afcee83 100644 --- a/manager/ram_logging/log_manager.py +++ b/src/ram_logging/log_manager.py @@ -1,7 +1,7 @@ import logging import os -from src.manager.libs.process_utils import classproperty, singleton +from ..libs.process_utils import singleton @singleton diff --git a/user_code.py b/user_code.py new file mode 100644 index 0000000..ccfb7e1 --- /dev/null +++ b/user_code.py @@ -0,0 +1,211 @@ +from gui import GUI +from hal import HAL +from cv2 import cv2 +import numpy as np +import time +import math + + +# PID class +class PID: + def __init__(self, kp, kd, ki, st): + + self.kp = kp + self.kd = kd + self.ki = ki + self.last_error = 0 + self.last_output = 0 + self.last_time = 0 + self.st = st + self.last_sample = time.time() + self.iterm = 0 + + def set_lims(self, outmin, outmax): + self.outmax = outmax + self.outmin = outmin + + def calc(self, error): + + out = self.last_output + + # Calculate the time which has passed + diff_time = time.time() - self.last_sample + + if (diff_time >= self.st): + # Derivative part + diff_error = error - self.last_error + + # Integrative part (never higher than max) + self.iterm += error * self.ki + if (self.iterm > self.outmax): + self.iterm = self.outmax + elif (self.iterm < self.outmin): + self.iterm = self.outmin + + # Output (never higher than max) + out = self.kp * error + self.kd * diff_error + self.iterm + if (out > self.outmax): + out = self.outmax + elif (out < self.outmin): + out = self.outmin + + # Store info needed for next time + self.last_error = error + self.last_output = out + self.last_sample = time.time() + + return out + + +class ErrBuff: + def __init__(self, size): + self.size = size + self.ac_error = [] + self.nelems = 0 + self.next = 0 + + def add(self, error): + + # Check if buffer has to cycle + if self.next == self.size: self.next = 0 + + # Checks if already big enough + if self.nelems < self.size: + self.ac_error.append(error) + self.nelems += 1 + else: + self.ac_error[self.next] = error + + self.next += 1 + + def get_mean(self): + mean = 0 + # print(self.ac_error) + if (self.nelems > 0): mean = sum(self.ac_error) / self.nelems + + return mean + + +# Color filter +red_mask = ([17, 15, 70], [50, 56, 255]) +center_offset = 20 +center_margin = 10 +black_pixel = np.array([0, 0, 0]) + +# PID variables +direct = 0 + +# Angular pid +sp1 = 320 +kp_1 = 0.01 +kd_1 = 0.026 +ki_1 = 0.00011 +outmax_1 = 3 +outmin_1 = -3.5 + +# Linear pid +sp2 = center_offset + int(center_margin / 2) +kp_2 = 0.04 +kd_2 = 0.08 +ki_2 = 0 +outmax_2 = 6 +outmin_2 = -6 + +# Car variables +max_linear = 11 +max_lin_dec = 6 +error_thres = 25 + +# PIDS objects (angular and linear speed) +pid1 = PID(kp_1, kd_1, ki_1, 0.03) +pid1.set_lims(outmin_1, outmax_1) + +# buffer object +buff = ErrBuff(15) + + +# Apply the color mask to the raw img and return the filtered image +def filter_img(raw_image, c_mask): + lower = np.array(c_mask[0], dtype="uint8") + upper = np.array(c_mask[1], dtype="uint8") + + mask = cv2.inRange(raw_image, lower, upper) + f_img = cv2.bitwise_and(raw_image, raw_image, mask=mask) + + return f_img + + +# Gets a reference position between (center+offset, center+offset+margin) +def get_line_ref(img, offset, margin): + height = img.shape[0] + width = img.shape[1] + + center_row = int(height / 2) + offset + + c_x = 0 + c_y = 0 + npixels = 0 + + for x in range(width): + for y in range(center_row, center_row + margin): + # Get pixel val and compare it with values for black + pixel_val = img[y][x] + comparison = (pixel_val == black_pixel) + + if not comparison.all(): + c_x += x + c_y += y + npixels += 1 + + if (npixels > 0): + c_x /= npixels + c_y /= npixels + + return (int(c_x), int(c_y)) + + +# Shows a debug image with the reference point and the set point +def show_debug_img(img, ref): + dimensions = img.shape + height = dimensions[0] + width = dimensions[1] + + set_point = (int(width / 2), int(height / 2)) + + img = cv2.circle(img, ref, 4, (255, 255, 0), -1) + # img = cv2.circle(img, set_point, 5, (0, 255, 255), -1) + img = cv2.line(img, (set_point[0], 0), (set_point[0], height), (0, 255, 0), thickness=1) + + GUI.showImage(img) + + + + +raw_img = HAL.getImage() +f_img = filter_img(raw_img, red_mask) + +# The reference used for angular speed calculation +ref1 = get_line_ref(f_img, center_offset, center_margin) + +if (ref1 != (0, 0)): + + # Error calculation + ref1_x = ref1[0] + error = sp1 - ref1_x + buff.add(abs(error)) + mean_error = round(buff.get_mean(), 2) + + norm_mean = mean_error / error_thres + if (norm_mean > 1): norm_mean = 1 + + linear_speed = max_linear - max_lin_dec * norm_mean + angular_speed = pid1.calc(error) + + # Control action + HAL.setW(angular_speed) + HAL.setV(linear_speed) +else: + HAL.setW(0) + HAL.setV(0) + +show_debug_img(f_img, ref1) \ No newline at end of file