From 834dacd8e83b089fed6323ca00432871400196ea Mon Sep 17 00:00:00 2001 From: Kavindu Prabhath Methpura <150885116+KavinduMethpura@users.noreply.github.com> Date: Wed, 27 Aug 2025 12:59:48 +0530 Subject: [PATCH] started the base structure --- .idea/.gitignore | 3 + .../inspectionProfiles/profiles_settings.xml | 6 ++ .idea/misc.xml | 7 ++ .idea/modules.xml | 8 ++ .idea/robot-library-python.iml | 10 +++ .idea/vcs.xml | 6 ++ src/robot_emulator/__init__.py | 2 + src/robot_emulator/base.py | 88 +++++++++++++++++++ src/robot_emulator/maze_following.py | 0 src/robot_emulator/mqtt_client.py | 0 src/robot_emulator/obstacle_avoid.py | 0 src/robot_emulator/sample_robot.py | 0 src/robot_emulator/sensors.py | 0 13 files changed, 130 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/robot-library-python.iml create mode 100644 .idea/vcs.xml create mode 100644 src/robot_emulator/base.py create mode 100644 src/robot_emulator/maze_following.py create mode 100644 src/robot_emulator/mqtt_client.py create mode 100644 src/robot_emulator/obstacle_avoid.py create mode 100644 src/robot_emulator/sample_robot.py create mode 100644 src/robot_emulator/sensors.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..1f20186 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..64db8e1 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/robot-library-python.iml b/.idea/robot-library-python.iml new file mode 100644 index 0000000..ea6edcf --- /dev/null +++ b/.idea/robot-library-python.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/robot_emulator/__init__.py b/src/robot_emulator/__init__.py index e69de29..8f03e21 100644 --- a/src/robot_emulator/__init__.py +++ b/src/robot_emulator/__init__.py @@ -0,0 +1,2 @@ +#main API +from .base import RobotState \ No newline at end of file diff --git a/src/robot_emulator/base.py b/src/robot_emulator/base.py new file mode 100644 index 0000000..3752e70 --- /dev/null +++ b/src/robot_emulator/base.py @@ -0,0 +1,88 @@ +# Robot emulator base class +# This file holds core framework for robot emulation +# RobotState - define robot state +# Motion - send move/ rotate command over mqtt +# Virtual Robot - base class for robot emulation + +import time +import threading +import paho.mqtt.client as mqtt + +class RobotState: + """Define robot states""" + + BEGIN = "BEGIN" + RUN = "RUN" + WAIT ="WAIT" + +class Motion: + """Handle movement""" + def __init__(self,mqtt_client,robot_id): + self.client = mqtt_client + self.robot_id = robot_id + + def move_distance(self, speed, distance): + """Move forward a fixed distance""" + self.client.publish(f"robots/{self.robot_id}/motion", f"MOVE {speed} {distance}") + + def rotate_degree(self, speed, angle): + """Rotate by an angle""" + self.client.publish(f"robots/{self.robot_id}/motion", f"ROTATE {speed} {angle}") + + def stop(self): + """Stop movement""" + self.client.publish(f"robots/{self.robot_id}/motion", "STOP") + + def move(self, left_speed, right_speed, duration): + """Move with differential speeds for a duration""" + self.client.publish(f"robots/{self.robot_id}/motion", f"DRIVE {left_speed} {right_speed} {duration}") + +class VirtualRobot(threading.Thread): + """Base class for virtual robot emulation""" + """ + Extend this class and implement 'setup()' and 'loop()' + """ + + def __init__(self, robot_id, x=0, y=0, heading=0, mqtt_config = None): + super().__init__() + self.robot_id = robot_id + self.x = x + self.y = y + self.heading = heading + self.state = RobotState.BEGIN + self.client = mqtt.Client() + self.motion = Motion(self.client, self.robot_id) + + #configure mqtt + if mqtt_config: + self.client.username_pw_set( + mqtt_config.get("username"), + mqtt_config.get("password") + ) + self.client.connect( + mqtt_config.get("server","127.0.0.1"), + mqtt_config.get("port",1883), + mqtt_config.get("keepalive",60) + ) + + def setup(self): + """Run once when the robot starts""" + print(f"Robot {self.robot_id} setup complete") + self.state = RobotState.RUN + + def loop(self): + """Main loop, override this method""" + print(f"Robot {self.robot_id} running at position ({self.x}, {self.y}) heading {self.heading}") + pass + + def run(self): + """Mian execution loop""" + self.setup() + while True: + try: + self.loop() + time.sleep(0.1) # Small delay to prevent CPU overload + + except Exception as e: + print(f"Error in robot {self.robot_id}: {e}") + break \ No newline at end of file diff --git a/src/robot_emulator/maze_following.py b/src/robot_emulator/maze_following.py new file mode 100644 index 0000000..e69de29 diff --git a/src/robot_emulator/mqtt_client.py b/src/robot_emulator/mqtt_client.py new file mode 100644 index 0000000..e69de29 diff --git a/src/robot_emulator/obstacle_avoid.py b/src/robot_emulator/obstacle_avoid.py new file mode 100644 index 0000000..e69de29 diff --git a/src/robot_emulator/sample_robot.py b/src/robot_emulator/sample_robot.py new file mode 100644 index 0000000..e69de29 diff --git a/src/robot_emulator/sensors.py b/src/robot_emulator/sensors.py new file mode 100644 index 0000000..e69de29