From 3324f8184ac878b8e8ecf25ab061eb8a83d5bbc0 Mon Sep 17 00:00:00 2001 From: mirrin00 Date: Thu, 28 Jul 2022 16:25:44 +0100 Subject: [PATCH 01/72] Added config.py --- config.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 config.py diff --git a/config.py b/config.py new file mode 100644 index 0000000..ff9c1a0 --- /dev/null +++ b/config.py @@ -0,0 +1,7 @@ +from utils.load_camera_settings import load_camera_settings + +camera_matrix, camera_distortion = load_camera_settings() + +print(camera_matrix) +print(camera_distortion) +MARKER_LEN = 6.5 # in cm From d16ead027205cc18e51cd5e16339fbe8c36dcb60 Mon Sep 17 00:00:00 2001 From: mirrin00 Date: Fri, 29 Jul 2022 11:46:52 +0100 Subject: [PATCH 02/72] Minor fixes --- .gitignore | 1 + camera_settings_kamikadze.npy | Bin 0 -> 368 bytes config.py | 3 +-- ros/wiki/axis.md | 6 ++++++ 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 camera_settings_kamikadze.npy diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/camera_settings_kamikadze.npy b/camera_settings_kamikadze.npy new file mode 100644 index 0000000000000000000000000000000000000000..88bb4e3220f6daa9d831edc04af2f423a9ca6827 GIT binary patch literal 368 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlV+i=qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= zXCxM+0{I%oIts>`ItsN4WCO0Wb*JK`7xXwVK*93Iee=t#>frpvw|f%1s(KtwtvWm9 zLO~f^9Ht&Zf3TlSi9ZZ=6ig}f$FU!6#!rq;-oIaK%E!q1L-y5yk$YauF4%vq-L>#t QM!Nlzl^bUy)n45X0FIVmqW}N^ literal 0 HcmV?d00001 diff --git a/config.py b/config.py index ff9c1a0..7557406 100644 --- a/config.py +++ b/config.py @@ -1,7 +1,6 @@ from utils.load_camera_settings import load_camera_settings + camera_matrix, camera_distortion = load_camera_settings() -print(camera_matrix) -print(camera_distortion) MARKER_LEN = 6.5 # in cm diff --git a/ros/wiki/axis.md b/ros/wiki/axis.md index 5e656f8..5551a8e 100644 --- a/ros/wiki/axis.md +++ b/ros/wiki/axis.md @@ -7,6 +7,12 @@ * Third value is down/up, where up is positive value * Fourth value is rotation counterclockwise/clockwise, where clockwise is positive value +For all values, the absolute maximum is `100`. + +First three values are measured in *cm/s*. + +Fourth value (*rotation*) is measured in *0.5 degrees/s*. This means that with value of `100`, the drone will rotate clockwise at speed of *`50` degrees per second* + ## Twist axis * `Twist.linear.x` is backward/forward, where forward is positive value From 16ece4e359642661568feef621bcf4b4b7531cbe Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Thu, 14 Mar 2024 21:13:12 +0000 Subject: [PATCH 03/72] rtl_device_connection: added connect method --- rtl_device/connect.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 rtl_device/connect.py diff --git a/rtl_device/connect.py b/rtl_device/connect.py new file mode 100644 index 0000000..228d145 --- /dev/null +++ b/rtl_device/connect.py @@ -0,0 +1,41 @@ +import json +import wifi +import subprocess +from loguru import logger +# Необходимо установить wireless-tools, ifupdown + + +def readNetworkConfiguration(json_path): + with open(json_path) as json_file: + return json.load(json_file) + + +def connect(iface, ssid, password) -> bool: + logger.info(f"Connecting device \'{iface}\' to \'{ssid}\'") + scanner = wifi.Cell.all(iface) + available_networks = [cell.ssid for cell in scanner] + if ssid not in available_networks: + logger.error(f"SSID {ssid} unreacheble") + return False + try: + output = subprocess.check_output( + ['nmcli', 'device', 'wifi', 'connect', ssid, 'password', password, 'ifname', iface]).decode(encoding='utf-8').replace("\n", "") + + if "successfully" in str(output): + logger.success(f'Device \'{iface}\' successfully connected to \'{ssid}\'') + return True + else: + logger.error(f"Error while connecting to {ssid}") + logger.error(output) + return False + except Exception as e: + logger.critical(e) + logger.debug(output) + + return False + + +if __name__ == "__main__": + ifaces = readNetworkConfiguration("networks.json")["ifaces"] + for iface in ifaces: + connect(iface, ifaces[iface]['ssid'], ifaces[iface]['password']) From 3f9af0b328b886fec37a178a5d2003196ce9d4b7 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Fri, 15 Mar 2024 09:47:11 +0000 Subject: [PATCH 04/72] createDockerNetwork method added --- requirements.txt | 4 ++++ rtl_device/connect.py | 37 +++++++++++++++++++++++++++++++++---- rtl_device/networks.json | 16 ++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 rtl_device/networks.json diff --git a/requirements.txt b/requirements.txt index da738ef..4876a9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,7 @@ numpy opencv-python opencv-contrib-python djitellopy +wifi +netifaces +docker +loguru \ No newline at end of file diff --git a/rtl_device/connect.py b/rtl_device/connect.py index 228d145..f36aa81 100644 --- a/rtl_device/connect.py +++ b/rtl_device/connect.py @@ -1,8 +1,11 @@ import json import wifi import subprocess +import netifaces +import docker from loguru import logger -# Необходимо установить wireless-tools, ifupdown + +# Необходимо установить wireless-tools, network-manager def readNetworkConfiguration(json_path): @@ -14,15 +17,18 @@ def connect(iface, ssid, password) -> bool: logger.info(f"Connecting device \'{iface}\' to \'{ssid}\'") scanner = wifi.Cell.all(iface) available_networks = [cell.ssid for cell in scanner] + + output = "" if ssid not in available_networks: logger.error(f"SSID {ssid} unreacheble") return False try: output = subprocess.check_output( ['nmcli', 'device', 'wifi', 'connect', ssid, 'password', password, 'ifname', iface]).decode(encoding='utf-8').replace("\n", "") - if "successfully" in str(output): - logger.success(f'Device \'{iface}\' successfully connected to \'{ssid}\'') + logger.info(netifaces.ifaddresses(iface)) + logger.success( + f'Device \'{iface}\' successfully connected to \'{ssid}\'') return True else: logger.error(f"Error while connecting to {ssid}") @@ -35,7 +41,30 @@ def connect(iface, ssid, password) -> bool: return False +def createDockerNetwork(name, iface, gateway, subnet): + options = dict({("parent", iface)}) + srv_pool = docker.types.IPAMPool(subnet=subnet, gateway=gateway) + ipam = docker.types.IPAMConfig(pool_configs=[srv_pool]) + client = docker.from_env() + docker_networks = client.networks.list([name]) + if docker_networks != []: + logger.warning( + f"Network with name {name} already exists, removing it...") + network = client.networks.get(docker_networks[0].id) + network.remove() + logger.info(f'Removed network with id {docker_networks[0].id}') + logger.info(f'Creating network with name {name}') + client.networks.create(name, "macvlan", options, ipam) + + if __name__ == "__main__": - ifaces = readNetworkConfiguration("networks.json")["ifaces"] + config = readNetworkConfiguration("networks.json") + ifaces = config["ifaces"] + docker_networks = config["docker_networks"] + for iface in ifaces: connect(iface, ifaces[iface]['ssid'], ifaces[iface]['password']) + for network in docker_networks: + createDockerNetwork(network, docker_networks[network]["iface"], + docker_networks[network]["gateway"], + docker_networks[network]["subnet"]) diff --git a/rtl_device/networks.json b/rtl_device/networks.json new file mode 100644 index 0000000..f5ba6c6 --- /dev/null +++ b/rtl_device/networks.json @@ -0,0 +1,16 @@ +{ + "ifaces" : { + "wlx90de80aa59de" : { + "ssid" : "", + "password" : "" + } + }, + "docker_networks" : { + "dji-tello-1" : { + "iface" : "", + "gateway" : "192.168.0.1", + "subnet" : "192.168.0.0/24" + } + } + +} \ No newline at end of file From 47258a313862e273b518ff902eebd134e3692425 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Fri, 15 Mar 2024 19:00:58 +0000 Subject: [PATCH 05/72] codestyle fix --- rtl_device/connect.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rtl_device/connect.py b/rtl_device/connect.py index f36aa81..15fb9f3 100644 --- a/rtl_device/connect.py +++ b/rtl_device/connect.py @@ -3,7 +3,9 @@ import subprocess import netifaces import docker +import sys from loguru import logger +from typing import NoReturn # Необходимо установить wireless-tools, network-manager @@ -13,7 +15,7 @@ def readNetworkConfiguration(json_path): return json.load(json_file) -def connect(iface, ssid, password) -> bool: +def connect(iface: str, ssid: str, password: str) -> bool: logger.info(f"Connecting device \'{iface}\' to \'{ssid}\'") scanner = wifi.Cell.all(iface) available_networks = [cell.ssid for cell in scanner] @@ -37,11 +39,12 @@ def connect(iface, ssid, password) -> bool: except Exception as e: logger.critical(e) logger.debug(output) + sys.exit(-1) return False -def createDockerNetwork(name, iface, gateway, subnet): +def createDockerNetwork(name: str, iface: str, gateway: str, subnet: str) -> NoReturn: options = dict({("parent", iface)}) srv_pool = docker.types.IPAMPool(subnet=subnet, gateway=gateway) ipam = docker.types.IPAMConfig(pool_configs=[srv_pool]) @@ -61,7 +64,7 @@ def createDockerNetwork(name, iface, gateway, subnet): config = readNetworkConfiguration("networks.json") ifaces = config["ifaces"] docker_networks = config["docker_networks"] - + for iface in ifaces: connect(iface, ifaces[iface]['ssid'], ifaces[iface]['password']) for network in docker_networks: From 7c177a492e2d2ed7e2e5fdb3baaec4ff924a2e9a Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sat, 16 Mar 2024 07:15:30 +0000 Subject: [PATCH 06/72] deleted comments --- rtl_device/connect.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/rtl_device/connect.py b/rtl_device/connect.py index 15fb9f3..01dca6d 100644 --- a/rtl_device/connect.py +++ b/rtl_device/connect.py @@ -7,8 +7,6 @@ from loguru import logger from typing import NoReturn -# Необходимо установить wireless-tools, network-manager - def readNetworkConfiguration(json_path): with open(json_path) as json_file: From e4d9ea32ab7c8515ebd12565fc31f1f036acb7e3 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Sun, 17 Mar 2024 07:34:49 +0300 Subject: [PATCH 07/72] create folder --- Code/Tokun_Grigory_1303/documentation.docx | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Code/Tokun_Grigory_1303/documentation.docx diff --git a/Code/Tokun_Grigory_1303/documentation.docx b/Code/Tokun_Grigory_1303/documentation.docx new file mode 100644 index 0000000..e69de29 From aa762528d2b6bcee2e048eccf1179f1bb79b2988 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Sun, 17 Mar 2024 07:37:49 +0300 Subject: [PATCH 08/72] delete folder --- Code/Tokun_Grigory_1303/documentation.docx | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Code/Tokun_Grigory_1303/documentation.docx diff --git a/Code/Tokun_Grigory_1303/documentation.docx b/Code/Tokun_Grigory_1303/documentation.docx deleted file mode 100644 index e69de29..0000000 From c1e66f292574cb1d73eecff2ad35c7183c1186b6 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Sun, 17 Mar 2024 07:42:40 +0300 Subject: [PATCH 09/72] create folder --- Code/Tokun_Grigory_1303/documentation.docx | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Code/Tokun_Grigory_1303/documentation.docx diff --git a/Code/Tokun_Grigory_1303/documentation.docx b/Code/Tokun_Grigory_1303/documentation.docx new file mode 100644 index 0000000..e69de29 From ebb399accd70af46d39e636c112a2608c0b35bca Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:27:56 +0300 Subject: [PATCH 10/72] first version of DroneController --- Code/Tokun_Grigory_1303/documentation.docx | Bin 0 -> 12775 bytes Code/Tokun_Grigory_1303/scripts/script.py | 7 ++ .../scripts/solutions/following/config.py | 27 +++++ .../solutions/following/follow_marker.py | 99 ++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 Code/Tokun_Grigory_1303/scripts/script.py create mode 100644 Code/Tokun_Grigory_1303/scripts/solutions/following/config.py create mode 100644 Code/Tokun_Grigory_1303/scripts/solutions/following/follow_marker.py diff --git a/Code/Tokun_Grigory_1303/documentation.docx b/Code/Tokun_Grigory_1303/documentation.docx index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..90e2206d7d587caf9970b64ab503528d3a641efb 100644 GIT binary patch literal 12775 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 literal 0 HcmV?d00001 diff --git a/Code/Tokun_Grigory_1303/scripts/script.py b/Code/Tokun_Grigory_1303/scripts/script.py new file mode 100644 index 0000000..74ad57d --- /dev/null +++ b/Code/Tokun_Grigory_1303/scripts/script.py @@ -0,0 +1,7 @@ +from solutions.following.follow_marker import FollowMarkerWithCoords + + +if __name__ == "__main__": + initial_position = (0, 0, 0) + marker_follower = FollowMarkerWithCoords(initial_position) + marker_follower.main() diff --git a/Code/Tokun_Grigory_1303/scripts/solutions/following/config.py b/Code/Tokun_Grigory_1303/scripts/solutions/following/config.py new file mode 100644 index 0000000..b8ff354 --- /dev/null +++ b/Code/Tokun_Grigory_1303/scripts/solutions/following/config.py @@ -0,0 +1,27 @@ +import cv2 +import numpy as np + +# Config for following solutions + +FRAME_RATE = 30 +FRAME_SIZE = (960, 720) +MARKER_SIZE = 50 # in pixels +MARKER_SIZE_RANGE = 15 +MARKER_NUMBER = 304 +X_RANGE = 125 +Y_RANGE = 125 +TIMEOUT = 10 +STEP = 25 +Z_STEP = 25 +SPEED = 50 +QUEUE_SIZE = 100 +MARKER_LEN = 0.1 +camera_matrix = np.array([[1000, 0, 320], [0, 1000, 240], [0, 0, 1]], dtype=np.float32) +camera_distortion = np.array([0.1, 0.2, 0.0, 0.0, 0.0], dtype=np.float32) + +DISTANCE = 125 # in cm +DISTANCE_RANGE = 25 + +ARUCO_DICT = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_250) +ARUCO_PARAMS = cv2.aruco.DetectorParameters() +ARUCO_DET = cv2.aruco.ArucoDetector(ARUCO_DICT, ARUCO_PARAMS) diff --git a/Code/Tokun_Grigory_1303/scripts/solutions/following/follow_marker.py b/Code/Tokun_Grigory_1303/scripts/solutions/following/follow_marker.py new file mode 100644 index 0000000..807e5dc --- /dev/null +++ b/Code/Tokun_Grigory_1303/scripts/solutions/following/follow_marker.py @@ -0,0 +1,99 @@ +import cv2 +import time +import math +import numpy as np +from queue import Queue, Empty +from drone.drone import Drone +from config import * +from config import camera_matrix, camera_distortion, MARKER_LEN +from solutions.following.state import State +from utils.write_text import write_status_on_image + +class FollowMarkerWithCoords: + + def __init__(self, initial_position=(0, 0, 0)): + self.video_writer = cv2.VideoWriter('drone_stream.avi', cv2.VideoWriter_fourcc(*'XVID'), FRAME_RATE, FRAME_SIZE) + self.actions = Queue(QUEUE_SIZE) + self.last_state = State.START + self.last_time = time.process_time() + self.last_battery_charge = 0 + self.is_stopped = False + self.initial_position = initial_position + + def stop(self): + self.is_stopped = True + + def get_state(self, tvec): + marker_x, marker_y, marker_z = tvec[2], tvec[0], tvec[1] + x = y = z = 0 + if abs(marker_y) > 20: + y = -int(marker_y) + if abs(marker_z) > 20: + z = -int(marker_z) + if abs(DISTANCE - marker_x) > DISTANCE_RANGE: + x = int(marker_x - DISTANCE) + if x == 0 and y == 0 and z == 0: + return None + return (State.MOVE, np.array([x, y, z], dtype=np.int32)) + + def find_marker(self, frame): + corners, ids, rejected = cv2.aruco.detectMarkers(frame, ARUCO_DICT, parameters=ARUCO_PARAMS) + if ids is not None: + for i in range(len(ids)): + if ids[i] == MARKER_NUMBER: + return (ids[i], corners[i]) + return None + + def move_to_marker(self, m_corner): + self.last_time = time.process_time() + _ , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) + state = self.get_state(tvecs[0][0]) + if state is not None: + self.actions.put(state) + self.last_state = state + + def process_frame(self, frame): + ids = None + is_find = True + if self.last_state == State.READY: + ret = self.find_marker(frame) + if ret is not None: + marker_id, marker_corner = ret + frame = cv2.aruco.drawDetectedMarkers(frame, np.array([marker_corner]), np.array([marker_id])) + self.move_to_marker(marker_corner) + else: + if time.process_time() - self.last_time > TIMEOUT: + print("Marker not found. Landing...") + self.actions.put((State.END, None)) + self.last_state = State.END + is_find = False + if is_find: + write_status_on_image(frame, {"Battery": f"{self.last_battery_charge}%", "Last state": self.last_state}) + self.video_writer.write(cv2.resize(frame, FRAME_SIZE)) + return frame + + def drone_instructions(self, tello): + tello.takeoff() + tello.move_up(50) + tello.move_xyz_speed(*self.initial_position, SPEED) # Поднимаемся на начальную позицию + self.last_time = time.process_time() + self.last_state = State.READY + while not self.is_stopped: + try: + state, movements = self.actions.get(block=False, timeout=0.25) + self.actions.task_done() + if state == State.END: + break + elif state == State.MOVE: + x, y, z = movements + tello.go_xyz_speed(int(x), int(y), int(z), SPEED) + except Empty: + self.last_state = State.READY + self.last_battery_charge = tello.get_battery() + tello.land() + + def main(self): + self.is_stopped = False + drone = Drone(self.drone_instructions, self.process_frame, show_stream=True) + drone.run_program() + self.video_writer.release() \ No newline at end of file From 58dcf3f857557702fad45f1ccd1057798f6eba76 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Sun, 17 Mar 2024 12:08:03 +0300 Subject: [PATCH 11/72] rename branch and folder --- .../DocumentationDroneContoller.docx | Bin .../Tokun_Grigory_1303 => swarm}/scripts/script.py | 0 .../scripts/solutions/following/config.py | 0 .../scripts/solutions/following/follow_marker.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename Code/Tokun_Grigory_1303/documentation.docx => swarm/DocumentationDroneContoller.docx (100%) rename {Code/Tokun_Grigory_1303 => swarm}/scripts/script.py (100%) rename {Code/Tokun_Grigory_1303 => swarm}/scripts/solutions/following/config.py (100%) rename {Code/Tokun_Grigory_1303 => swarm}/scripts/solutions/following/follow_marker.py (100%) diff --git a/Code/Tokun_Grigory_1303/documentation.docx b/swarm/DocumentationDroneContoller.docx similarity index 100% rename from Code/Tokun_Grigory_1303/documentation.docx rename to swarm/DocumentationDroneContoller.docx diff --git a/Code/Tokun_Grigory_1303/scripts/script.py b/swarm/scripts/script.py similarity index 100% rename from Code/Tokun_Grigory_1303/scripts/script.py rename to swarm/scripts/script.py diff --git a/Code/Tokun_Grigory_1303/scripts/solutions/following/config.py b/swarm/scripts/solutions/following/config.py similarity index 100% rename from Code/Tokun_Grigory_1303/scripts/solutions/following/config.py rename to swarm/scripts/solutions/following/config.py diff --git a/Code/Tokun_Grigory_1303/scripts/solutions/following/follow_marker.py b/swarm/scripts/solutions/following/follow_marker.py similarity index 100% rename from Code/Tokun_Grigory_1303/scripts/solutions/following/follow_marker.py rename to swarm/scripts/solutions/following/follow_marker.py From ae331910cfbe5e63d870c80f43ad1f511633e38b Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Mon, 18 Mar 2024 12:48:32 +0300 Subject: [PATCH 12/72] Function to write coordinates --- swarm/DocumentationDroneContoller.docx | Bin 12775 -> 13366 bytes swarm/scripts/avi/drone_stream.avi | Bin 0 -> 5686 bytes swarm/scripts/script.py | 14 ++++++++++---- swarm/scripts/solutions/following/config.py | 10 ++++++---- .../solutions/following/follow_marker.py | 15 ++++++--------- 5 files changed, 22 insertions(+), 17 deletions(-) create mode 100644 swarm/scripts/avi/drone_stream.avi diff --git a/swarm/DocumentationDroneContoller.docx b/swarm/DocumentationDroneContoller.docx index 90e2206d7d587caf9970b64ab503528d3a641efb..5902da8d2188fbc681a9edb23a056565b663d932 100644 GIT binary patch delta 4751 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 J3PVr`001%;G}8b8 literal 0 HcmV?d00001 diff --git a/swarm/scripts/script.py b/swarm/scripts/script.py index 74ad57d..4e57acc 100644 --- a/swarm/scripts/script.py +++ b/swarm/scripts/script.py @@ -1,7 +1,13 @@ -from solutions.following.follow_marker import FollowMarkerWithCoords - +import argparse +from swarm.scripts.solutions.following.follow_marker import FollowMarkerWithCoords if __name__ == "__main__": - initial_position = (0, 0, 0) + parser = argparse.ArgumentParser(description="Follow Marker with Initial Position") + parser.add_argument("-x", "--x_position", type=float, default=0, help="Initial X Position") + parser.add_argument("-y", "--y_position", type=float, default=0, help="Initial Y Position") + parser.add_argument("-z", "--z_position", type=float, default=0, help="Initial Z Position") + args = parser.parse_args() + + initial_position = (args.x_position, args.y_position, args.z_position) marker_follower = FollowMarkerWithCoords(initial_position) - marker_follower.main() + marker_follower.main() \ No newline at end of file diff --git a/swarm/scripts/solutions/following/config.py b/swarm/scripts/solutions/following/config.py index b8ff354..1322b67 100644 --- a/swarm/scripts/solutions/following/config.py +++ b/swarm/scripts/solutions/following/config.py @@ -1,5 +1,7 @@ import cv2 +import os import numpy as np +from utils.load_camera_settings import load_camera_settings # Config for following solutions @@ -15,13 +17,13 @@ Z_STEP = 25 SPEED = 50 QUEUE_SIZE = 100 -MARKER_LEN = 0.1 -camera_matrix = np.array([[1000, 0, 320], [0, 1000, 240], [0, 0, 1]], dtype=np.float32) -camera_distortion = np.array([0.1, 0.2, 0.0, 0.0, 0.0], dtype=np.float32) +MARKER_LEN = 6.5 + +camera_matrix, camera_distortion = load_camera_settings() + DISTANCE = 125 # in cm DISTANCE_RANGE = 25 ARUCO_DICT = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_250) ARUCO_PARAMS = cv2.aruco.DetectorParameters() -ARUCO_DET = cv2.aruco.ArucoDetector(ARUCO_DICT, ARUCO_PARAMS) diff --git a/swarm/scripts/solutions/following/follow_marker.py b/swarm/scripts/solutions/following/follow_marker.py index 807e5dc..37daef9 100644 --- a/swarm/scripts/solutions/following/follow_marker.py +++ b/swarm/scripts/solutions/following/follow_marker.py @@ -1,18 +1,16 @@ -import cv2 import time -import math -import numpy as np from queue import Queue, Empty from drone.drone import Drone -from config import * -from config import camera_matrix, camera_distortion, MARKER_LEN +from swarm.scripts.solutions.following.config import * +from swarm.scripts.solutions.following.config import camera_matrix, camera_distortion, MARKER_LEN from solutions.following.state import State from utils.write_text import write_status_on_image + class FollowMarkerWithCoords: - def __init__(self, initial_position=(0, 0, 0)): - self.video_writer = cv2.VideoWriter('drone_stream.avi', cv2.VideoWriter_fourcc(*'XVID'), FRAME_RATE, FRAME_SIZE) + def __init__(self, initial_position=()): + self.video_writer = cv2.VideoWriter('avi/drone_stream.avi', cv2.VideoWriter_fourcc(*'XVID'), FRAME_RATE, FRAME_SIZE) self.actions = Queue(QUEUE_SIZE) self.last_state = State.START self.last_time = time.process_time() @@ -74,8 +72,7 @@ def process_frame(self, frame): def drone_instructions(self, tello): tello.takeoff() - tello.move_up(50) - tello.move_xyz_speed(*self.initial_position, SPEED) # Поднимаемся на начальную позицию + tello.move_xyz_speed(*self.initial_position, SPEED) # начальная позиция self.last_time = time.process_time() self.last_state = State.READY while not self.is_stopped: From d47c2c0a26dfacaef1253d4e4a89fef056d677f9 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:05:54 +0300 Subject: [PATCH 13/72] Corrections --- .idea/.name | 1 + .../inspectionProfiles/profiles_settings.xml | 6 +++ .idea/misc.xml | 4 ++ .idea/tello-dev.iml | 6 +++ .idea/vcs.xml | 6 +++ .idea/workspace.xml | 44 ++++++++++++++++++ avi/drone_stream.avi | 0 swarm/scripts/script.py => script.py | 0 swarm/scripts/avi/drone_stream.avi | Bin 5686 -> 0 bytes swarm/~$cumentationDroneContoller.docx | Bin 0 -> 162 bytes 10 files changed, 67 insertions(+) create mode 100644 .idea/.name create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/tello-dev.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 avi/drone_stream.avi rename swarm/scripts/script.py => script.py (100%) delete mode 100644 swarm/scripts/avi/drone_stream.avi create mode 100644 swarm/~$cumentationDroneContoller.docx diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..be59299 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +script.py \ No newline at end of file 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..97adc1f --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/tello-dev.iml b/.idea/tello-dev.iml new file mode 100644 index 0000000..9d38f51 --- /dev/null +++ b/.idea/tello-dev.iml @@ -0,0 +1,6 @@ + + + + + \ 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/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..42ef78c --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + 1710724629051 + + + + \ No newline at end of file diff --git a/avi/drone_stream.avi b/avi/drone_stream.avi new file mode 100644 index 0000000..e69de29 diff --git a/swarm/scripts/script.py b/script.py similarity index 100% rename from swarm/scripts/script.py rename to script.py diff --git a/swarm/scripts/avi/drone_stream.avi b/swarm/scripts/avi/drone_stream.avi deleted file mode 100644 index 301a06955fd6b400f8672aeeb97306a2583dfdd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5686 zcmWIYbaT@aV_(I9i=kOhG3|3Cl}I>3B^ z38+6!11JE(F#8x8BpASEEs=*Qh0|W4e%=y5yIG(j1_mj~aLG}|Xb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2C72m#Re01I&7AwMNI2Z%C$j0j(2_atbXMhYn9 z>F4I}8SECq2W0ysmZh0m=$V`885$TcfI{mBaFk~hjE2By2#mZC0F@A+k<{G$vdqks J3PVr`001%;G}8b8 diff --git a/swarm/~$cumentationDroneContoller.docx b/swarm/~$cumentationDroneContoller.docx new file mode 100644 index 0000000000000000000000000000000000000000..a25d5faa86fda518bdfb0d85e29053e908c78a2a GIT binary patch literal 162 zcmZQC$ Date: Mon, 18 Mar 2024 13:06:38 +0300 Subject: [PATCH 14/72] Corrections --- .idea/.name | 1 - .../inspectionProfiles/profiles_settings.xml | 6 --- .idea/misc.xml | 4 -- .idea/tello-dev.iml | 6 --- .idea/vcs.xml | 6 --- .idea/workspace.xml | 44 ------------------- 6 files changed, 67 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/tello-dev.iml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index be59299..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -script.py \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 97adc1f..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/tello-dev.iml b/.idea/tello-dev.iml deleted file mode 100644 index 9d38f51..0000000 --- a/.idea/tello-dev.iml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 42ef78c..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 1710724629051 - - - - \ No newline at end of file From becefb9378903902d00c7182f7a6f317ca3265c2 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Mon, 25 Mar 2024 14:39:55 +0300 Subject: [PATCH 15/72] Delete swarm/DocumentationDroneContoller.docx --- swarm/DocumentationDroneContoller.docx | Bin 13366 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 swarm/DocumentationDroneContoller.docx diff --git a/swarm/DocumentationDroneContoller.docx b/swarm/DocumentationDroneContoller.docx deleted file mode 100644 index 5902da8d2188fbc681a9edb23a056565b663d932..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13366 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 S+ouO`fbKWe;yuf6NB Date: Mon, 25 Mar 2024 14:40:04 +0300 Subject: [PATCH 16/72] Delete swarm/~$cumentationDroneContoller.docx --- swarm/~$cumentationDroneContoller.docx | Bin 162 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 swarm/~$cumentationDroneContoller.docx diff --git a/swarm/~$cumentationDroneContoller.docx b/swarm/~$cumentationDroneContoller.docx deleted file mode 100644 index a25d5faa86fda518bdfb0d85e29053e908c78a2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162 zcmZQC$ Date: Wed, 27 Mar 2024 02:00:48 +0300 Subject: [PATCH 17/72] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c18dd8d..9701f3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__/ +avi/ From 39865ba00b709f48d4675e780754f6bee8370903 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 02:01:09 +0300 Subject: [PATCH 18/72] Delete avi directory --- avi/drone_stream.avi | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 avi/drone_stream.avi diff --git a/avi/drone_stream.avi b/avi/drone_stream.avi deleted file mode 100644 index e69de29..0000000 From a3467443fad9df7b6211cabe37476e63a8141576 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 02:01:49 +0300 Subject: [PATCH 19/72] Rename script.py to run_singel_drone.py --- script.py => run_singel_drone.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename script.py => run_singel_drone.py (96%) diff --git a/script.py b/run_singel_drone.py similarity index 96% rename from script.py rename to run_singel_drone.py index 4e57acc..ff24fc4 100644 --- a/script.py +++ b/run_singel_drone.py @@ -10,4 +10,4 @@ initial_position = (args.x_position, args.y_position, args.z_position) marker_follower = FollowMarkerWithCoords(initial_position) - marker_follower.main() \ No newline at end of file + marker_follower.main() From 6a08103c56392ec23fd6406d01f55a7b4727811a Mon Sep 17 00:00:00 2001 From: ngoyen05 Date: Wed, 27 Mar 2024 11:12:08 +0300 Subject: [PATCH 20/72] drone_container_25 --- Dockerfile | 13 +++++++++++++ requirements.txt | 2 +- run_container.py | 27 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 Dockerfile create mode 100644 run_container.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6b01c06 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM python + +RUN apt-get update && \ + apt-get install -y python3-pip ffmpeg libsm6 libxext6 + +COPY requirements.txt /tmp/ +RUN pip3 install --no-cache-dir -r /tmp/requirements.txt + +WORKDIR /app + +COPY . /app + +CMD ["python", "run_singel_drone.py"] diff --git a/requirements.txt b/requirements.txt index 4876a9a..8eb64a9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,4 @@ djitellopy wifi netifaces docker -loguru \ No newline at end of file +loguru diff --git a/run_container.py b/run_container.py new file mode 100644 index 0000000..23c7bdd --- /dev/null +++ b/run_container.py @@ -0,0 +1,27 @@ +import docker + +def run_container(image_name, container_name, requirements_file): + client = docker.from_env() + try: + # Считываем содержимое файла requirements.txt + with open(requirements_file, 'r') as file: + requirements = file.read().splitlines() + + # Строим контейнер + container = client.containers.run( + image=image_name, + name=container_name, + detach=True, + volumes={requirements_file: {'bind': '/requirements.txt', 'mode': 'ro'}}, + command=f"sh -c 'pip install -r /requirements.txt && tail -f /dev/null'" + ) + print(f"Container {container_name} started successfully.") + except docker.errors.APIError as e: + print(f"Error starting container: {e}") + +if __name__ == "__main__": + image_name = "python" + container_name = "droner" + requirements_file = "requirements.txt" + + run_container(image_name, container_name, requirements_file) From 101e64842f5837df131ac73a1a31163770ba71c3 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 16:58:55 +0300 Subject: [PATCH 21/72] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 621ba3a..ba33ac6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +# Итерация 2 +## Версия 1 +Чтобы запустить рой из одного дрона [Запуск одиночного дрона](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: +`pip install -r requirements.txt` +`python run_singel_drone.py -x 50 -y 30 -z 20` + # Обучение управлению дронами Tello ## Зависимости From 323b352cb3775f174ee65bb9d006ddf18dd81c02 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 16:59:15 +0300 Subject: [PATCH 22/72] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ba33ac6..3a9590b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Итерация 2 ## Версия 1 -Чтобы запустить рой из одного дрона [Запуск одиночного дрона](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: -`pip install -r requirements.txt` +Чтобы запустить рой из одного дрона [Запуск одиночного дрона](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: +`pip install -r requirements.txt` `python run_singel_drone.py -x 50 -y 30 -z 20` # Обучение управлению дронами Tello From 95729d3c3c56904646e5339dcab54fa9f8bfa876 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:16:35 +0300 Subject: [PATCH 23/72] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a9590b..bc0c808 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,15 @@ # Итерация 2 ## Версия 1 -Чтобы запустить рой из одного дрона [Запуск одиночного дрона](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: +Чтобы запустить рой из одного дрона [(полная инструкция запуска одиночного дрона)](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: `pip install -r requirements.txt` `python run_singel_drone.py -x 50 -y 30 -z 20` +## Скрипты для создания физических сетевых интерфейсов +Инструкция находится на [wiki-странице](https://github.com/OSLL/tello-dev/wiki/%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%BE). Необходим wifi-адаптер Realtek 802.11ac. +## Для создания контейнеров для каждого дрона, подключаемых к созданной сети +`docker build -t single_drone_swarm .` +'python3 run_swarm.py' + + # Обучение управлению дронами Tello From f625bc27a2e212df63df9670ad33d4ab9ad41053 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:17:26 +0300 Subject: [PATCH 24/72] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bc0c808..dfc10fb 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,12 @@ ## Скрипты для создания физических сетевых интерфейсов Инструкция находится на [wiki-странице](https://github.com/OSLL/tello-dev/wiki/%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%BE). Необходим wifi-адаптер Realtek 802.11ac. ## Для создания контейнеров для каждого дрона, подключаемых к созданной сети -`docker build -t single_drone_swarm .` -'python3 run_swarm.py' +`docker build -t single_drone_swarm .` +`python run_swarm.py` +# +# # Обучение управлению дронами Tello From 5161f35a795b1f23de3c62ec47d988d2a3d049cc Mon Sep 17 00:00:00 2001 From: elcstazi Date: Wed, 27 Mar 2024 20:16:51 +0300 Subject: [PATCH 25/72] swarm_container_25 --- Dockerfile | 13 +++++++++++++ run_container.py | 27 +++++++++++++++++++++++++++ run_swarm.py | 21 +++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 Dockerfile create mode 100644 run_container.py create mode 100644 run_swarm.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6b01c06 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM python + +RUN apt-get update && \ + apt-get install -y python3-pip ffmpeg libsm6 libxext6 + +COPY requirements.txt /tmp/ +RUN pip3 install --no-cache-dir -r /tmp/requirements.txt + +WORKDIR /app + +COPY . /app + +CMD ["python", "run_singel_drone.py"] diff --git a/run_container.py b/run_container.py new file mode 100644 index 0000000..23c7bdd --- /dev/null +++ b/run_container.py @@ -0,0 +1,27 @@ +import docker + +def run_container(image_name, container_name, requirements_file): + client = docker.from_env() + try: + # Считываем содержимое файла requirements.txt + with open(requirements_file, 'r') as file: + requirements = file.read().splitlines() + + # Строим контейнер + container = client.containers.run( + image=image_name, + name=container_name, + detach=True, + volumes={requirements_file: {'bind': '/requirements.txt', 'mode': 'ro'}}, + command=f"sh -c 'pip install -r /requirements.txt && tail -f /dev/null'" + ) + print(f"Container {container_name} started successfully.") + except docker.errors.APIError as e: + print(f"Error starting container: {e}") + +if __name__ == "__main__": + image_name = "python" + container_name = "droner" + requirements_file = "requirements.txt" + + run_container(image_name, container_name, requirements_file) diff --git a/run_swarm.py b/run_swarm.py new file mode 100644 index 0000000..3f05480 --- /dev/null +++ b/run_swarm.py @@ -0,0 +1,21 @@ +import docker +from loguru import logger +from rtl_device.connect import readNetworkConfiguration + + +def start_containers(image_name, network_name, num_containers): + client = docker.from_env() + network = client.networks.get(network_name) + + for i in range(num_containers): + container_name = f"{image_name}_{i+1}" + container = client.containers.run(image=image_name, detach=True, name=container_name, network=network_name) + logger.info(f"Container {container_name} started and attached to network {network_name}") + +if __name__ == "__main__": + config = readNetworkConfiguration("./rtl_device/networks.json") + image_name = 'single_drone_swarm' + network_name = list(config["docker_networks"].keys())[0] + num_containers = 3 + + start_containers(image_name, network_name, num_containers) From 40bc07bd57fb95b49387d509ad8c9ac86ef119e6 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 21:53:21 +0300 Subject: [PATCH 26/72] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dfc10fb..7947004 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Чтобы запустить рой из одного дрона [(полная инструкция запуска одиночного дрона)](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: `pip install -r requirements.txt` `python run_singel_drone.py -x 50 -y 30 -z 20` +[Видео запуска из лаборатории](https://drive.google.com/file/d/1U_BEifhNsm7GAZkeG5-yhBLDRsZn3LQ_/view) ## Скрипты для создания физических сетевых интерфейсов Инструкция находится на [wiki-странице](https://github.com/OSLL/tello-dev/wiki/%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%BE). Необходим wifi-адаптер Realtek 802.11ac. ## Для создания контейнеров для каждого дрона, подключаемых к созданной сети From b28936f1c3df79683bbe98e9ba89152d583ce3e2 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 22:00:16 +0300 Subject: [PATCH 27/72] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 7947004..3980838 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ `docker build -t single_drone_swarm .` `python run_swarm.py` +## Презентация и видео +[Видео запуска из лаборатории](https://drive.google.com/file/d/1U_BEifhNsm7GAZkeG5-yhBLDRsZn3LQ_/view) +[ОУПРПО. Итерация 2. Проект 12.pdf](https://github.com/OSLL/tello-dev/files/14780046/2.12.pdf) # # From 3885a99becc4ed5c8f4df55a86f05e41a0ce1d12 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 22:00:41 +0300 Subject: [PATCH 28/72] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3980838..2a61c22 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ `python run_swarm.py` ## Презентация и видео -[Видео запуска из лаборатории](https://drive.google.com/file/d/1U_BEifhNsm7GAZkeG5-yhBLDRsZn3LQ_/view) -[ОУПРПО. Итерация 2. Проект 12.pdf](https://github.com/OSLL/tello-dev/files/14780046/2.12.pdf) +[Видео запуска из лаборатории](https://drive.google.com/file/d/1U_BEifhNsm7GAZkeG5-yhBLDRsZn3LQ_/view) +Презентация:[ОУПРПО. Итерация 2. Проект 12.pdf](https://github.com/OSLL/tello-dev/files/14780046/2.12.pdf) # # From de9ca32557874adafc2c345e5df55eeacdd73d04 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 22:43:10 +0300 Subject: [PATCH 29/72] Update run_swarm.py --- run_swarm.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/run_swarm.py b/run_swarm.py index 3f05480..d28d28e 100644 --- a/run_swarm.py +++ b/run_swarm.py @@ -2,16 +2,36 @@ from loguru import logger from rtl_device.connect import readNetworkConfiguration +def createDockerNetwork(name: str) -> None: + client = docker.from_env() + client.networks.create(name) def start_containers(image_name, network_name, num_containers): client = docker.from_env() - network = client.networks.get(network_name) + try: + network = client.networks.get(network_name) + except docker.errors.NotFound: + logger.warning(f"Network '{network_name}' not found, creating it...") + createDockerNetwork(network_name) # Создаем сеть + network = client.networks.get(network_name) for i in range(num_containers): container_name = f"{image_name}_{i+1}" - container = client.containers.run(image=image_name, detach=True, name=container_name, network=network_name) + + try: + old_container = client.containers.get(container_name) + logger.info(f"Removing old container: {container_name}") + old_container.remove(force=True) + except docker.errors.NotFound: + pass + + container = client.containers.run(image=image_name, detach=True, name=container_name, network=network_name, stdout=True) logger.info(f"Container {container_name} started and attached to network {network_name}") + container_logs = container.logs().decode("utf-8") + logger.info(f"Container logs for {container_name}:") + logger.info(container_logs) + if __name__ == "__main__": config = readNetworkConfiguration("./rtl_device/networks.json") image_name = 'single_drone_swarm' @@ -19,3 +39,4 @@ def start_containers(image_name, network_name, num_containers): num_containers = 3 start_containers(image_name, network_name, num_containers) + From da5d155b3a447ef8548c780ac45b868ec64a19de Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 22:44:34 +0300 Subject: [PATCH 30/72] Update README.md --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2a61c22..7a4492e 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # Итерация 2 ## Версия 1 -Чтобы запустить рой из одного дрона [(полная инструкция запуска одиночного дрона)](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: -`pip install -r requirements.txt` -`python run_singel_drone.py -x 50 -y 30 -z 20` +Чтобы запустить рой из одного дрона [(wiki скрипта)](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: +`docker build -t single_drone_swarm .` +`sudo docker run single_drone_swarm` [Видео запуска из лаборатории](https://drive.google.com/file/d/1U_BEifhNsm7GAZkeG5-yhBLDRsZn3LQ_/view) -## Скрипты для создания физических сетевых интерфейсов -Инструкция находится на [wiki-странице](https://github.com/OSLL/tello-dev/wiki/%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%BE). Необходим wifi-адаптер Realtek 802.11ac. +## Скрипты для создания физических сетевых интерфейсов в сети docker +Инструкция находится на [wiki-странице](https://github.com/OSLL/tello-dev/wiki/%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%BE). Работает по wifi-адаптер Realtek 802.11ac. ## Для создания контейнеров для каждого дрона, подключаемых к созданной сети `docker build -t single_drone_swarm .` - -`python run_swarm.py` +`python run_swarm.py` +Контейнеры отключаются через 21 секунду без дронов. ## Презентация и видео [Видео запуска из лаборатории](https://drive.google.com/file/d/1U_BEifhNsm7GAZkeG5-yhBLDRsZn3LQ_/view) Презентация:[ОУПРПО. Итерация 2. Проект 12.pdf](https://github.com/OSLL/tello-dev/files/14780046/2.12.pdf) From 545576aecf5bf299ae369bc1d03a2f3940d53bc7 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Wed, 27 Mar 2024 22:45:29 +0300 Subject: [PATCH 31/72] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7a4492e..c147abb 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # Итерация 2 ## Версия 1 -Чтобы запустить рой из одного дрона [(wiki скрипта)](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: -`docker build -t single_drone_swarm .` -`sudo docker run single_drone_swarm` +Чтобы запустить рой из одного дрона [(wiki скрипта)](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: +`docker build -t single_drone_swarm .` +`sudo docker run single_drone_swarm` [Видео запуска из лаборатории](https://drive.google.com/file/d/1U_BEifhNsm7GAZkeG5-yhBLDRsZn3LQ_/view) ## Скрипты для создания физических сетевых интерфейсов в сети docker Инструкция находится на [wiki-странице](https://github.com/OSLL/tello-dev/wiki/%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%BE). Работает по wifi-адаптер Realtek 802.11ac. -## Для создания контейнеров для каждого дрона, подключаемых к созданной сети -`docker build -t single_drone_swarm .` -`python run_swarm.py` +## Для создания контейнеров для каждого дрона, подключаемых к созданной сети +`docker build -t single_drone_swarm .` +`python run_swarm.py` Контейнеры отключаются через 21 секунду без дронов. ## Презентация и видео [Видео запуска из лаборатории](https://drive.google.com/file/d/1U_BEifhNsm7GAZkeG5-yhBLDRsZn3LQ_/view) From 17a727313f9a2c1212693569062941a2e3d5cb2c Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Sun, 7 Apr 2024 05:28:28 +0300 Subject: [PATCH 32/72] Little Changes --- swarm/scripts/solutions/following/config.py | 3 -- ...llow_marker.py => follow_marker_coords.py} | 36 +++++++++++-------- swarm/scripts/solutions/following/state.py | 9 +++++ 3 files changed, 30 insertions(+), 18 deletions(-) rename swarm/scripts/solutions/following/{follow_marker.py => follow_marker_coords.py} (75%) create mode 100644 swarm/scripts/solutions/following/state.py diff --git a/swarm/scripts/solutions/following/config.py b/swarm/scripts/solutions/following/config.py index 1322b67..661f38c 100644 --- a/swarm/scripts/solutions/following/config.py +++ b/swarm/scripts/solutions/following/config.py @@ -1,6 +1,4 @@ import cv2 -import os -import numpy as np from utils.load_camera_settings import load_camera_settings # Config for following solutions @@ -21,7 +19,6 @@ camera_matrix, camera_distortion = load_camera_settings() - DISTANCE = 125 # in cm DISTANCE_RANGE = 25 diff --git a/swarm/scripts/solutions/following/follow_marker.py b/swarm/scripts/solutions/following/follow_marker_coords.py similarity index 75% rename from swarm/scripts/solutions/following/follow_marker.py rename to swarm/scripts/solutions/following/follow_marker_coords.py index 37daef9..43b7e4f 100644 --- a/swarm/scripts/solutions/following/follow_marker.py +++ b/swarm/scripts/solutions/following/follow_marker_coords.py @@ -1,22 +1,29 @@ +import cv2 import time +import math +import numpy as np from queue import Queue, Empty from drone.drone import Drone -from swarm.scripts.solutions.following.config import * +from swarm.scripts.solutions.following.config import FRAME_RATE, FRAME_SIZE, DISTANCE, DISTANCE_RANGE,\ + ARUCO_DICT, ARUCO_PARAMS, QUEUE_SIZE, TIMEOUT, MARKER_NUMBER, SPEED from swarm.scripts.solutions.following.config import camera_matrix, camera_distortion, MARKER_LEN -from solutions.following.state import State +from swarm.scripts.solutions.following.state import State from utils.write_text import write_status_on_image -class FollowMarkerWithCoords: +def dist_beetwen_points(p1, p2): + return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) - def __init__(self, initial_position=()): - self.video_writer = cv2.VideoWriter('avi/drone_stream.avi', cv2.VideoWriter_fourcc(*'XVID'), FRAME_RATE, FRAME_SIZE) + +class FollowMarkerWithCoords(): + + def __init__(self): + self.video_writer = cv2.VideoWriter('drone_stream.avi', cv2.VideoWriter_fourcc(*'XVID'), FRAME_RATE, FRAME_SIZE) self.actions = Queue(QUEUE_SIZE) self.last_state = State.START self.last_time = time.process_time() self.last_battery_charge = 0 self.is_stopped = False - self.initial_position = initial_position def stop(self): self.is_stopped = True @@ -25,10 +32,10 @@ def get_state(self, tvec): marker_x, marker_y, marker_z = tvec[2], tvec[0], tvec[1] x = y = z = 0 if abs(marker_y) > 20: - y = -int(marker_y) + y = -int(marker_y) if marker_y < 0 else 20 if abs(marker_z) > 20: - z = -int(marker_z) - if abs(DISTANCE - marker_x) > DISTANCE_RANGE: + z = -int(marker_z) if marker_z < 0 else 20 + if abs(marker_x - DISTANCE) > DISTANCE_RANGE: x = int(marker_x - DISTANCE) if x == 0 and y == 0 and z == 0: return None @@ -61,18 +68,16 @@ def process_frame(self, frame): self.move_to_marker(marker_corner) else: if time.process_time() - self.last_time > TIMEOUT: - print("Marker not found. Landing...") + print("Send END") self.actions.put((State.END, None)) self.last_state = State.END - is_find = False - if is_find: - write_status_on_image(frame, {"Battery": f"{self.last_battery_charge}%", "Last state": self.last_state}) - self.video_writer.write(cv2.resize(frame, FRAME_SIZE)) + write_status_on_image(frame, {"Battery": f"{self.last_battery_charge}%", "Last state": self.last_state}) + self.video_writer.write(cv2.resize(frame, FRAME_SIZE)) return frame def drone_instructions(self, tello): tello.takeoff() - tello.move_xyz_speed(*self.initial_position, SPEED) # начальная позиция + tello.move_up(50) self.last_time = time.process_time() self.last_state = State.READY while not self.is_stopped: @@ -83,6 +88,7 @@ def drone_instructions(self, tello): break elif state == State.MOVE: x, y, z = movements + print(movements) tello.go_xyz_speed(int(x), int(y), int(z), SPEED) except Empty: self.last_state = State.READY diff --git a/swarm/scripts/solutions/following/state.py b/swarm/scripts/solutions/following/state.py new file mode 100644 index 0000000..8f5b4d4 --- /dev/null +++ b/swarm/scripts/solutions/following/state.py @@ -0,0 +1,9 @@ +from enum import Enum, auto + + +class State(Enum): + END = auto() + READY = auto() + START = auto() + MOVE = auto() + ROTATE = auto() \ No newline at end of file From a96dc9e154c807c7204e15bb68a8bcb1a1eb03b1 Mon Sep 17 00:00:00 2001 From: ngoyen05 Date: Sat, 13 Apr 2024 12:15:41 +0300 Subject: [PATCH 33/72] Delete_interface --- Delete_interface_connect.py | 48 +++++++++++++++++++++++++++++++++++ Detele_interface_run_swarm.py | 39 ++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 Delete_interface_connect.py create mode 100644 Detele_interface_run_swarm.py diff --git a/Delete_interface_connect.py b/Delete_interface_connect.py new file mode 100644 index 0000000..1da5961 --- /dev/null +++ b/Delete_interface_connect.py @@ -0,0 +1,48 @@ +import subprocess + +# ваш код для подключения контейнеров + +# Данные о сетевых интерфейсах +network_info = """ +7: docker0: mtu 1500 qdisc noqueue state UP group default +link/ether 02:42:77:d0:1c:38 brd ff:ff:ff:ff:ff:ff +inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 +valid_lft forever preferred_lft forever +inet6 fe80::42:77ff:fed0:1c38/64 scope link +valid_lft forever preferred_lft forever +8: br-a04529330ebd: mtu 1500 qdisc noqueue state DOWN group default +link/ether 02:42:79:98:57:42 brd ff:ff:ff:ff:ff:ff +inet 172.18.0.1/16 brd 172.18.255.255 scope global br-a04529330ebd +valid_lft forever preferred_lft forever +10: vethe32f082@if9: mtu 1500 qdisc noqueue master br-3ae656ee29b7 state UP group default +link/ether 16:bc:d1:b1:eb:2d brd ff:ff:ff:ff:ff:ff link-netnsid 1 +inet6 fe80::14bc:d1ff:feb1:eb2d/64 scope link +valid_lft forever preferred_lft forever +12: vetha2d4e99@if11: mtu 1500 qdisc noqueue master docker0 state UP group default +link/ether 42:1c:f3:87:c8:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0 +inet6 fe80::401c:f3ff:fe87:c804/64 scope link +valid_lft forever preferred_lft forever +14: vethd0e3234@if13: mtu 1500 qdisc noqueue master br-3ae656ee29b7 state UP group default +link/ether 56:57:4a:1f:13:12 brd ff:ff:ff:ff:ff:ff link-netnsid 2 +inet6 fe80::5457:4aff:fe1f:1312/64 scope link +valid_lft forever preferred_lft forever +26: dm-f1fef7f465f8: mtu 1500 qdisc noqueue state UNKNOWN group default +link/ether 52:aa:83:b0:a0:b9 brd ff:ff:ff:ff:ff:ff +inet6 fe80::80a0:7cff:fe8e:a9/64 scope link +valid_lft forever preferred_lft forever +""" + +# Разбиваем информацию на строки +lines = network_info.strip().split('\n') + +# Проходим по каждой строке +for line in lines: + # Разбиваем строку на части + parts = line.split() + # Проверяем, что строка содержит информацию о Docker-интерфейсе + if parts[1].startswith('br-'): + # Получаем имя интерфейса + interface_name = parts[1][:-1] # Убираем двоеточие в конце имени интерфейса + # Удаляем интерфейс + subprocess.run(["ip", "link", "delete", interface_name]) + print(f"Интерфейс {interface_name} удален") diff --git a/Detele_interface_run_swarm.py b/Detele_interface_run_swarm.py new file mode 100644 index 0000000..10c88ae --- /dev/null +++ b/Detele_interface_run_swarm.py @@ -0,0 +1,39 @@ +import subprocess + +# ваш код для запуска Docker Swarm + +# Данные о сетевых интерфейсах +network_info = """ +3: br-cfe453156857: mtu 1500 qdisc noqueue state DOWN group default +link/ether 02:42:a6:60:e9:36 brd ff:ff:ff:ff:ff:ff +inet 172.20.0.1/16 brd 172.20.255.255 scope global br-cfe453156857 +valid_lft forever preferred_lft forever +4: br-3ae656ee29b7: mtu 1500 qdisc noqueue state UP group default +link/ether 02:42:84:36:d7:f4 brd ff:ff:ff:ff:ff:ff +inet 172.23.0.1/16 brd 172.23.255.255 scope global br-3ae656ee29b7 +valid_lft forever preferred_lft forever +inet6 fe80::42:84ff:fe36:d7f4/64 scope link +valid_lft forever preferred_lft forever +5: br-55d74f66c2b8: mtu 1500 qdisc noqueue state DOWN group default +link/ether 02:42:98:96:2c:86 brd ff:ff:ff:ff:ff:ff +inet 172.21.0.1/16 brd 172.21.255.255 scope global br-55d74f66c2b8 +valid_lft forever preferred_lft forever +6: br-57a5652aba95: mtu 1500 qdisc noqueue state DOWN group default +link/ether 02:42:89:ba:29:47 brd ff:ff:ff:ff:ff:ff +inet 172.19.0.1/16 brd 172.19.255.255 scope global br-57a5652aba95 +""" + +# Разбиваем информацию на строки +lines = network_info.strip().split('\n') + +# Проходим по каждой строке +for line in lines: + # Разбиваем строку на части + parts = line.split() + # Проверяем, что строка содержит информацию о Docker-интерфейсе + if parts[1].startswith('br-'): + # Получаем имя интерфейса + interface_name = parts[1][:-1] # Убираем двоеточие в конце имени интерфейса + # Удаляем интерфейс + subprocess.run(["ip", "link", "delete", interface_name]) + print(f"Интерфейс {interface_name} удален") From 83effa6e36a08ad264c9faef8fd74f9825c92ee1 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Sun, 14 Apr 2024 08:01:28 +0300 Subject: [PATCH 34/72] fixed main bug with following marker --- run_singel_drone.py | 12 ++---------- swarm/scripts/solutions/following/config.py | 10 +++++----- .../solutions/following/follow_marker_coords.py | 12 ++++++++---- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/run_singel_drone.py b/run_singel_drone.py index ff24fc4..b7d91c6 100644 --- a/run_singel_drone.py +++ b/run_singel_drone.py @@ -1,13 +1,5 @@ -import argparse -from swarm.scripts.solutions.following.follow_marker import FollowMarkerWithCoords +from swarm.scripts.solutions.following.follow_marker_coords import FollowMarkerWithCoords if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Follow Marker with Initial Position") - parser.add_argument("-x", "--x_position", type=float, default=0, help="Initial X Position") - parser.add_argument("-y", "--y_position", type=float, default=0, help="Initial Y Position") - parser.add_argument("-z", "--z_position", type=float, default=0, help="Initial Z Position") - args = parser.parse_args() - - initial_position = (args.x_position, args.y_position, args.z_position) - marker_follower = FollowMarkerWithCoords(initial_position) + marker_follower = FollowMarkerWithCoords() marker_follower.main() diff --git a/swarm/scripts/solutions/following/config.py b/swarm/scripts/solutions/following/config.py index 661f38c..de91aba 100644 --- a/swarm/scripts/solutions/following/config.py +++ b/swarm/scripts/solutions/following/config.py @@ -1,13 +1,13 @@ import cv2 from utils.load_camera_settings import load_camera_settings -# Config for following solutions - FRAME_RATE = 30 FRAME_SIZE = (960, 720) MARKER_SIZE = 50 # in pixels MARKER_SIZE_RANGE = 15 -MARKER_NUMBER = 304 +MARKER_CENTER = 304 +MARKER_STOP = 303 # random +MARKER_MOVE = 302 # random X_RANGE = 125 Y_RANGE = 125 TIMEOUT = 10 @@ -19,8 +19,8 @@ camera_matrix, camera_distortion = load_camera_settings() -DISTANCE = 125 # in cm +DISTANCE = 60 # in cm DISTANCE_RANGE = 25 -ARUCO_DICT = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_250) +ARUCO_DICT = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_APRILTAG_36h11) ARUCO_PARAMS = cv2.aruco.DetectorParameters() diff --git a/swarm/scripts/solutions/following/follow_marker_coords.py b/swarm/scripts/solutions/following/follow_marker_coords.py index 43b7e4f..62f98bc 100644 --- a/swarm/scripts/solutions/following/follow_marker_coords.py +++ b/swarm/scripts/solutions/following/follow_marker_coords.py @@ -5,7 +5,7 @@ from queue import Queue, Empty from drone.drone import Drone from swarm.scripts.solutions.following.config import FRAME_RATE, FRAME_SIZE, DISTANCE, DISTANCE_RANGE,\ - ARUCO_DICT, ARUCO_PARAMS, QUEUE_SIZE, TIMEOUT, MARKER_NUMBER, SPEED + ARUCO_DICT, ARUCO_PARAMS, QUEUE_SIZE, TIMEOUT, MARKER_CENTER, MARKER_MOVE, MARKER_STOP, SPEED from swarm.scripts.solutions.following.config import camera_matrix, camera_distortion, MARKER_LEN from swarm.scripts.solutions.following.state import State from utils.write_text import write_status_on_image @@ -45,15 +45,19 @@ def find_marker(self, frame): corners, ids, rejected = cv2.aruco.detectMarkers(frame, ARUCO_DICT, parameters=ARUCO_PARAMS) if ids is not None: for i in range(len(ids)): - if ids[i] == MARKER_NUMBER: + if ids[i] == MARKER_CENTER: + return (ids[i], corners[i]) + if ids[i] == MARKER_STOP: + return (ids[i], corners[i]) + if ids[i] == MARKER_MOVE: return (ids[i], corners[i]) return None def move_to_marker(self, m_corner): self.last_time = time.process_time() - _ , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) + _ , rvecs, tvecs = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) state = self.get_state(tvecs[0][0]) - if state is not None: + if state == State.MOVE: self.actions.put(state) self.last_state = state From df6b85c05ccb57766ed3a2562e31433e17b31e60 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Sun, 14 Apr 2024 10:55:37 +0300 Subject: [PATCH 35/72] Delete Delete_interface_connect.py --- Delete_interface_connect.py | 48 ------------------------------------- 1 file changed, 48 deletions(-) delete mode 100644 Delete_interface_connect.py diff --git a/Delete_interface_connect.py b/Delete_interface_connect.py deleted file mode 100644 index 1da5961..0000000 --- a/Delete_interface_connect.py +++ /dev/null @@ -1,48 +0,0 @@ -import subprocess - -# ваш код для подключения контейнеров - -# Данные о сетевых интерфейсах -network_info = """ -7: docker0: mtu 1500 qdisc noqueue state UP group default -link/ether 02:42:77:d0:1c:38 brd ff:ff:ff:ff:ff:ff -inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 -valid_lft forever preferred_lft forever -inet6 fe80::42:77ff:fed0:1c38/64 scope link -valid_lft forever preferred_lft forever -8: br-a04529330ebd: mtu 1500 qdisc noqueue state DOWN group default -link/ether 02:42:79:98:57:42 brd ff:ff:ff:ff:ff:ff -inet 172.18.0.1/16 brd 172.18.255.255 scope global br-a04529330ebd -valid_lft forever preferred_lft forever -10: vethe32f082@if9: mtu 1500 qdisc noqueue master br-3ae656ee29b7 state UP group default -link/ether 16:bc:d1:b1:eb:2d brd ff:ff:ff:ff:ff:ff link-netnsid 1 -inet6 fe80::14bc:d1ff:feb1:eb2d/64 scope link -valid_lft forever preferred_lft forever -12: vetha2d4e99@if11: mtu 1500 qdisc noqueue master docker0 state UP group default -link/ether 42:1c:f3:87:c8:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0 -inet6 fe80::401c:f3ff:fe87:c804/64 scope link -valid_lft forever preferred_lft forever -14: vethd0e3234@if13: mtu 1500 qdisc noqueue master br-3ae656ee29b7 state UP group default -link/ether 56:57:4a:1f:13:12 brd ff:ff:ff:ff:ff:ff link-netnsid 2 -inet6 fe80::5457:4aff:fe1f:1312/64 scope link -valid_lft forever preferred_lft forever -26: dm-f1fef7f465f8: mtu 1500 qdisc noqueue state UNKNOWN group default -link/ether 52:aa:83:b0:a0:b9 brd ff:ff:ff:ff:ff:ff -inet6 fe80::80a0:7cff:fe8e:a9/64 scope link -valid_lft forever preferred_lft forever -""" - -# Разбиваем информацию на строки -lines = network_info.strip().split('\n') - -# Проходим по каждой строке -for line in lines: - # Разбиваем строку на части - parts = line.split() - # Проверяем, что строка содержит информацию о Docker-интерфейсе - if parts[1].startswith('br-'): - # Получаем имя интерфейса - interface_name = parts[1][:-1] # Убираем двоеточие в конце имени интерфейса - # Удаляем интерфейс - subprocess.run(["ip", "link", "delete", interface_name]) - print(f"Интерфейс {interface_name} удален") From 5b249ab66aa44c8dfc3e684032b964d715688b4a Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Sun, 14 Apr 2024 10:55:49 +0300 Subject: [PATCH 36/72] Delete Detele_interface_run_swarm.py --- Detele_interface_run_swarm.py | 39 ----------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 Detele_interface_run_swarm.py diff --git a/Detele_interface_run_swarm.py b/Detele_interface_run_swarm.py deleted file mode 100644 index 10c88ae..0000000 --- a/Detele_interface_run_swarm.py +++ /dev/null @@ -1,39 +0,0 @@ -import subprocess - -# ваш код для запуска Docker Swarm - -# Данные о сетевых интерфейсах -network_info = """ -3: br-cfe453156857: mtu 1500 qdisc noqueue state DOWN group default -link/ether 02:42:a6:60:e9:36 brd ff:ff:ff:ff:ff:ff -inet 172.20.0.1/16 brd 172.20.255.255 scope global br-cfe453156857 -valid_lft forever preferred_lft forever -4: br-3ae656ee29b7: mtu 1500 qdisc noqueue state UP group default -link/ether 02:42:84:36:d7:f4 brd ff:ff:ff:ff:ff:ff -inet 172.23.0.1/16 brd 172.23.255.255 scope global br-3ae656ee29b7 -valid_lft forever preferred_lft forever -inet6 fe80::42:84ff:fe36:d7f4/64 scope link -valid_lft forever preferred_lft forever -5: br-55d74f66c2b8: mtu 1500 qdisc noqueue state DOWN group default -link/ether 02:42:98:96:2c:86 brd ff:ff:ff:ff:ff:ff -inet 172.21.0.1/16 brd 172.21.255.255 scope global br-55d74f66c2b8 -valid_lft forever preferred_lft forever -6: br-57a5652aba95: mtu 1500 qdisc noqueue state DOWN group default -link/ether 02:42:89:ba:29:47 brd ff:ff:ff:ff:ff:ff -inet 172.19.0.1/16 brd 172.19.255.255 scope global br-57a5652aba95 -""" - -# Разбиваем информацию на строки -lines = network_info.strip().split('\n') - -# Проходим по каждой строке -for line in lines: - # Разбиваем строку на части - parts = line.split() - # Проверяем, что строка содержит информацию о Docker-интерфейсе - if parts[1].startswith('br-'): - # Получаем имя интерфейса - interface_name = parts[1][:-1] # Убираем двоеточие в конце имени интерфейса - # Удаляем интерфейс - subprocess.run(["ip", "link", "delete", interface_name]) - print(f"Интерфейс {interface_name} удален") From 2586516b35aa3dd87466eeb83f125b413679587c Mon Sep 17 00:00:00 2001 From: ngoyen05 Date: Sun, 14 Apr 2024 18:21:04 +0300 Subject: [PATCH 37/72] delete_interface --- delete_interface.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 delete_interface.py diff --git a/delete_interface.py b/delete_interface.py new file mode 100644 index 0000000..7bb89fb --- /dev/null +++ b/delete_interface.py @@ -0,0 +1,12 @@ +import subprocess + +def delete_docker_interface(interface_name): + subprocess.run(["ip", "link", "delete", interface_name]) + print(f"Interface {interface_name} deleted.") + +def input_interface(): + interface_name = input("Enter the interface name to delete: ") + delete_docker_interface(interface_name) + +if __name__ == '__main__': + input_interface() \ No newline at end of file From 57aaa5ac34951079807a834491785c9443af06f7 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sun, 21 Apr 2024 15:01:16 +0300 Subject: [PATCH 38/72] deleted old version --- rtl_device/connect.py | 71 ---------------------------------------- rtl_device/networks.json | 16 --------- 2 files changed, 87 deletions(-) delete mode 100644 rtl_device/connect.py delete mode 100644 rtl_device/networks.json diff --git a/rtl_device/connect.py b/rtl_device/connect.py deleted file mode 100644 index 01dca6d..0000000 --- a/rtl_device/connect.py +++ /dev/null @@ -1,71 +0,0 @@ -import json -import wifi -import subprocess -import netifaces -import docker -import sys -from loguru import logger -from typing import NoReturn - - -def readNetworkConfiguration(json_path): - with open(json_path) as json_file: - return json.load(json_file) - - -def connect(iface: str, ssid: str, password: str) -> bool: - logger.info(f"Connecting device \'{iface}\' to \'{ssid}\'") - scanner = wifi.Cell.all(iface) - available_networks = [cell.ssid for cell in scanner] - - output = "" - if ssid not in available_networks: - logger.error(f"SSID {ssid} unreacheble") - return False - try: - output = subprocess.check_output( - ['nmcli', 'device', 'wifi', 'connect', ssid, 'password', password, 'ifname', iface]).decode(encoding='utf-8').replace("\n", "") - if "successfully" in str(output): - logger.info(netifaces.ifaddresses(iface)) - logger.success( - f'Device \'{iface}\' successfully connected to \'{ssid}\'') - return True - else: - logger.error(f"Error while connecting to {ssid}") - logger.error(output) - return False - except Exception as e: - logger.critical(e) - logger.debug(output) - sys.exit(-1) - - return False - - -def createDockerNetwork(name: str, iface: str, gateway: str, subnet: str) -> NoReturn: - options = dict({("parent", iface)}) - srv_pool = docker.types.IPAMPool(subnet=subnet, gateway=gateway) - ipam = docker.types.IPAMConfig(pool_configs=[srv_pool]) - client = docker.from_env() - docker_networks = client.networks.list([name]) - if docker_networks != []: - logger.warning( - f"Network with name {name} already exists, removing it...") - network = client.networks.get(docker_networks[0].id) - network.remove() - logger.info(f'Removed network with id {docker_networks[0].id}') - logger.info(f'Creating network with name {name}') - client.networks.create(name, "macvlan", options, ipam) - - -if __name__ == "__main__": - config = readNetworkConfiguration("networks.json") - ifaces = config["ifaces"] - docker_networks = config["docker_networks"] - - for iface in ifaces: - connect(iface, ifaces[iface]['ssid'], ifaces[iface]['password']) - for network in docker_networks: - createDockerNetwork(network, docker_networks[network]["iface"], - docker_networks[network]["gateway"], - docker_networks[network]["subnet"]) diff --git a/rtl_device/networks.json b/rtl_device/networks.json deleted file mode 100644 index f5ba6c6..0000000 --- a/rtl_device/networks.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "ifaces" : { - "wlx90de80aa59de" : { - "ssid" : "", - "password" : "" - } - }, - "docker_networks" : { - "dji-tello-1" : { - "iface" : "", - "gateway" : "192.168.0.1", - "subnet" : "192.168.0.0/24" - } - } - -} \ No newline at end of file From 3e97b32b1a74c060e9d33790715314320368cb55 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sun, 21 Apr 2024 15:01:52 +0300 Subject: [PATCH 39/72] refactored connection --- swarm/scripts/networking/networking.py | 150 +++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 swarm/scripts/networking/networking.py diff --git a/swarm/scripts/networking/networking.py b/swarm/scripts/networking/networking.py new file mode 100644 index 0000000..b46e5f5 --- /dev/null +++ b/swarm/scripts/networking/networking.py @@ -0,0 +1,150 @@ +import json +import subprocess +import sys +from jsonschema import validate +from jsonschema.validators import Draft202012Validator + + +class Networking: + """ + Class for configuring network and routing based on a JSON configuration file. + + Attributes: + PORTS (list): List of ports for routing. + """ + + PORTS = [8889, 8890, 11111] + + def __init__(self, config: dict): + """ + Initializes the Networking class object. + + Args: + config (dict): Network configuration in dictionary format. + """ + self.__mark = 1 + for iface in config["ifaces"]: + for port in Networking.PORTS: + self.__routing(iface, port, config["ifaces"][iface]["ip"]) + self.__connection(config) + + def __connection(self, config: dict): + """ + Establishes connection to Wi-Fi networks specified in the configuration. + + Args: + config (dict): Network configuration in dictionary format. + """ + for iface in config["ifaces"]: + ssid = config['ifaces'][iface]['ssid'] + password = config['ifaces'][iface]['password'] + try: + output = subprocess.check_output( + ['nmcli', 'device', 'wifi']).decode(encoding='utf-8').replace("\n", "") + + output = subprocess.check_output( + ['nmcli', 'device', 'wifi', 'connect', ssid, 'password', + password, 'ifname', iface]).decode(encoding='utf-8').replace("\n", "") + except subprocess.CalledProcessError as e: + print(f"Failed to connect to {ssid} on {iface}. Error: {e}") + except Exception as e: + print( + f"An error occurred while connecting to {ssid} on {iface}. Error: {e}") + + def __routing(self, iface: str, port: int, ip: str): + """ + Configures routing for a specific network interface, port, and IP address. + + Args: + iface (str): Network interface. + port (int): Port for routing. + ip (str): IP address for routing. + """ + try: + output = subprocess.check_output( + ['iptables', '-t', 'nat', '-A', 'PREROUTING', '-i', iface, '-p', + 'udp', '--dport', str(port), '-j', 'DNAT', '--to-destination', ip] + ).decode(encoding='utf-8').replace("\n", "") + + output = subprocess.check_output( + ['iptables', '-t', 'mangle', '-A', 'PREROUTING', '-s', ip, '-j', 'MARK', + '--set-mark', str(self.__mark)]).decode(encoding='utf-8').replace("\n", "") + + output = subprocess.check_output( + ['ip', 'route', 'add', 'default', 'dev', + iface, 'table', str(self.__mark * 100)]).decode(encoding='utf-8').replace("\n", "") + + output = subprocess.check_output( + ['ip', 'rule', 'add', 'fwmark', str(self.__mark), + 'table', str(self.__mark * 100)]).decode(encoding='utf-8').replace("\n", "") + + self.__mark += 1 + except subprocess.CalledProcessError as e: + print(f"Error occurred while setting up routing: {e}") + except Exception as e: + print(f"An error occurred while setting up routing: {e}") + + +def read_network_configuration(json_path): + """ + Reads and validates the network configuration from a JSON file. + + Args: + json_path (str): Path to the JSON file containing the network configuration. + + Returns: + dict: Network configuration in dictionary format. + """ + schema = { + "type": "object", + "properties": { + "ifaces": { + "type": "object", + "patternProperties": { + "^[a-zA-Z0-9-]*$": { + "type": "object", + "properties": { + "ssid": {"type": "string"}, + "password": {"type": "string"}, + "ip": {"type": "string", "format": "ipv4"} + }, + "required": ["ssid", "password", "ip"] + } + } + } + }, + "required": ["ifaces"] + } + + try: + with open(json_path) as json_file: + config = json.load(json_file) + validate(instance=config, schema=schema, + format_checker=Draft202012Validator.FORMAT_CHECKER) + return config + except FileNotFoundError: + print(f"File '{json_path}' not found.") + except json.JSONDecodeError as e: + print(f"Error decoding JSON from '{json_path}': {e}") + except Exception as e: + print(f"An error occurred while reading network configuration: {e}") + return {} + + +def main(json_path): + """ + Main function of the program. + + Args: + json_path (str): Path to the JSON file containing the network configuration. + """ + config = read_network_configuration(json_path) + if config: + networking = Networking(config) + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: python script.py ") + sys.exit(1) + main(sys.argv[1]) From c562d5ee7d5b04b2ca1a8023f41e2d0208b6a00e Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sun, 21 Apr 2024 15:04:41 +0300 Subject: [PATCH 40/72] timezone file; needs to install network-manager --- swarm/scripts/networking/localtime | Bin 0 -> 1535 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 swarm/scripts/networking/localtime diff --git a/swarm/scripts/networking/localtime b/swarm/scripts/networking/localtime new file mode 100644 index 0000000000000000000000000000000000000000..ddb3f4e99a1030f33b56fad986c8d9c16e59eb32 GIT binary patch literal 1535 zcmd_pOGs2v0Eh8&eK(rb!qglm&2)U$sA*0)IyEzjsUbNPSW%Qng3+OZ6j}@+wy8i0 zTv(Y|s6YLnFvfkYNAS_B#d(ZT{b1Q9Ad&UZz$TD9&D_x_Go1;Ov{Z)$BR5`SH5 z^c!xj-TLO770{2~!?v;O6<<2~a%X1yzByZObnc(+f7>=aAe@1L@*#I{^@&i>RWve~ zaC~IY6&@P4`5GPslaD0WhbPu1O}P_eCL0pxR)vy2#ZM$pdfe;AuS}$j_ABe{Zk2lN zys}+9t=6AwR%vZ}Rryb@XbY;rQULoBr(Q-$pRqgamOV6<%%A5I8 z`aJJdRpcF6o$*Xn&%97I;XzgN`j*=Dp-a`?y`<{KZ_4`1CzZc0^@tH379J565g8R7 z6CJf8Dth5#iCy-ITe<9u<=^=89B&aK!>RufJR^iCykNxW^I6W7Jw}`mWo|?Nw{jgK zVewqmU?dA+O%tiVzt43T>5K2n+)F>t@7C4(MLl<;zP&sez51>dd5#j{^ZE6yUz(S} z(^$BcUYI8#{QuC`Pkrrs7#c%5Ls~<6Gu6!@-68EE{h8_pkq%9Di%5^Ax=Ex Date: Sun, 21 Apr 2024 15:05:22 +0300 Subject: [PATCH 41/72] template for swarm node --- swarm/Dockerfile.swarm_node | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 swarm/Dockerfile.swarm_node diff --git a/swarm/Dockerfile.swarm_node b/swarm/Dockerfile.swarm_node new file mode 100644 index 0000000..7140be8 --- /dev/null +++ b/swarm/Dockerfile.swarm_node @@ -0,0 +1,8 @@ +FROM ubuntu:22.04 +RUN apt update \ + && apt install -y \ + netcat \ + tcpdump \ + iputils-ping + +CMD ["tcpdump", "port", "8889"] \ No newline at end of file From cd990e2157a1e7c55caf603d6903a7e8663e4485 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sun, 21 Apr 2024 15:06:23 +0300 Subject: [PATCH 42/72] added networking service dockerfile --- swarm/Dockerfile.networking | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 swarm/Dockerfile.networking diff --git a/swarm/Dockerfile.networking b/swarm/Dockerfile.networking new file mode 100644 index 0000000..bf64c12 --- /dev/null +++ b/swarm/Dockerfile.networking @@ -0,0 +1,16 @@ +FROM ubuntu:22.04 +COPY /scripts/networking/localtime /etc/localtime +RUN apt update \ + && apt install -y \ + network-manager \ + iptables \ + netcat \ + tcpdump \ + iputils-ping \ + python3 \ + python3-pip +RUN pip install --upgrade jsonschema +COPY networking.py /networking.py +COPY networks.json /networks.json + +ENTRYPOINT ["python3", "networking.py", "/networks.json"] \ No newline at end of file From 912d608bd305460a03138b313965cc4448b3aaeb Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sun, 21 Apr 2024 15:34:28 +0300 Subject: [PATCH 43/72] fixed json-schema pattern --- swarm/scripts/networking/networking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swarm/scripts/networking/networking.py b/swarm/scripts/networking/networking.py index b46e5f5..282da83 100644 --- a/swarm/scripts/networking/networking.py +++ b/swarm/scripts/networking/networking.py @@ -101,7 +101,7 @@ def read_network_configuration(json_path): "ifaces": { "type": "object", "patternProperties": { - "^[a-zA-Z0-9-]*$": { + "^[a-zA-Z0-9-]+$": { "type": "object", "properties": { "ssid": {"type": "string"}, From 37bb942270adaabed31f7497416a270b80f2aa0b Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sun, 21 Apr 2024 15:34:48 +0300 Subject: [PATCH 44/72] fixed paths to scripts --- swarm/Dockerfile.networking | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swarm/Dockerfile.networking b/swarm/Dockerfile.networking index bf64c12..8c7e57b 100644 --- a/swarm/Dockerfile.networking +++ b/swarm/Dockerfile.networking @@ -10,7 +10,7 @@ RUN apt update \ python3 \ python3-pip RUN pip install --upgrade jsonschema -COPY networking.py /networking.py -COPY networks.json /networks.json +COPY /scripts/networking/networking.py /networking.py +COPY /networks.json /networks.json ENTRYPOINT ["python3", "networking.py", "/networks.json"] \ No newline at end of file From b653a404cccb903d4b75a50fb8ef5b8d619f85e4 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sun, 21 Apr 2024 15:35:23 +0300 Subject: [PATCH 45/72] compose added --- swarm/docker-compose.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 swarm/docker-compose.yml diff --git a/swarm/docker-compose.yml b/swarm/docker-compose.yml new file mode 100644 index 0000000..302a72e --- /dev/null +++ b/swarm/docker-compose.yml @@ -0,0 +1,40 @@ +version: "3" +services: + networking: + build: + context: . + dockerfile: Dockerfile.networking + network_mode: "host" + container_name: networking + restart: no + privileged: true + volumes: + - /var/run/dbus:/var/run/dbus + + drone_1: + build: + context: . + dockerfile: Dockerfile.swarm_node + depends_on: + - networking + networks: + swarm: + ipv4_address: 172.18.0.3 + + drone_2: + build: + context: . + dockerfile: Dockerfile.swarm_node + depends_on: + - networking + networks: + swarm: + ipv4_address: 172.18.0.4 + +networks: + swarm: + driver: bridge + ipam: + config: + - subnet: 172.18.0.0/16 + gateway: 172.18.0.1 \ No newline at end of file From 257907b7a2fa6d2db62ff597dd56300a8b5d73d2 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Sun, 21 Apr 2024 15:35:32 +0300 Subject: [PATCH 46/72] json template added --- swarm/networks.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 swarm/networks.json diff --git a/swarm/networks.json b/swarm/networks.json new file mode 100644 index 0000000..decec15 --- /dev/null +++ b/swarm/networks.json @@ -0,0 +1,14 @@ +{ + "ifaces" : { + "" : { + "ssid" : "", + "password" : "", + "ip": "172.18.0.3" + }, + "": { + "ssid" : "", + "password" : "", + "ip": "172.18.0.4" + } + } +} From 3a3573fecb10964cf8dd4589aff6e9a336033b1f Mon Sep 17 00:00:00 2001 From: ngoyen05 Date: Thu, 25 Apr 2024 00:16:18 +0300 Subject: [PATCH 47/72] tests --- tests/docker_ci_workflow.yml | 35 +++++++++++++++++++++++++++++ tests/start_and_check_containers.sh | 12 ++++++++++ 2 files changed, 47 insertions(+) create mode 100644 tests/docker_ci_workflow.yml create mode 100644 tests/start_and_check_containers.sh diff --git a/tests/docker_ci_workflow.yml b/tests/docker_ci_workflow.yml new file mode 100644 index 0000000..5df49e8 --- /dev/null +++ b/tests/docker_ci_workflow.yml @@ -0,0 +1,35 @@ +name: Docker CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Docker + uses: docker/setup-action@v2 + + - name: Build and run containers + run: | + docker-compose up -d + sleep 5 + docker ps + + - name: Check containers status + run: | + if docker ps | grep -q "droner"; then + echo "Containers are running successfully" + else + echo "Error occurred while running containers" + exit 1 + fi diff --git a/tests/start_and_check_containers.sh b/tests/start_and_check_containers.sh new file mode 100644 index 0000000..19a0d39 --- /dev/null +++ b/tests/start_and_check_containers.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Запуск контейнеров +docker-compose up -d + +# Проверка статуса контейнеров +if docker ps | grep -q "droner"; then + echo "Контейнеры успешно запущены" +else + echo "Произошла ошибка при запуске контейнеров" + exit 1 +fi From f9353443568552854c594437fef2e8e9c93fa70b Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Thu, 25 Apr 2024 18:45:36 +0300 Subject: [PATCH 48/72] added rpc-servers --- swarm/Dockerfile.swarm_node | 10 ++++++---- swarm/Dockerfile.swarm_server | 10 ++++++++++ swarm/docker-compose.yml | 33 +++++++++++++++++++++++++++++++ swarm/scripts/rpc/server.py | 12 +++++++++++ swarm/scripts/rpc/swarm_server.py | 20 +++++++++++++++++++ 5 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 swarm/Dockerfile.swarm_server create mode 100644 swarm/scripts/rpc/server.py create mode 100644 swarm/scripts/rpc/swarm_server.py diff --git a/swarm/Dockerfile.swarm_node b/swarm/Dockerfile.swarm_node index 7140be8..db03de7 100644 --- a/swarm/Dockerfile.swarm_node +++ b/swarm/Dockerfile.swarm_node @@ -1,8 +1,10 @@ FROM ubuntu:22.04 RUN apt update \ && apt install -y \ - netcat \ - tcpdump \ - iputils-ping + python3 \ + python3-pip \ + && pip install jsonrpcserver +COPY /scripts/rpc/server.py server.py +EXPOSE 65000 -CMD ["tcpdump", "port", "8889"] \ No newline at end of file +CMD ["python3", "server.py"] \ No newline at end of file diff --git a/swarm/Dockerfile.swarm_server b/swarm/Dockerfile.swarm_server new file mode 100644 index 0000000..502329b --- /dev/null +++ b/swarm/Dockerfile.swarm_server @@ -0,0 +1,10 @@ +FROM ubuntu:22.04 +RUN apt update \ + && apt install -y \ + python3 \ + python3-pip \ + && pip install jsonrpcserver jsonrpcclient requests +COPY /scripts/rpc/swarm_server.py swarm_server.py +EXPOSE 65001 + +CMD ["python3", "swarm_server.py"] \ No newline at end of file diff --git a/swarm/docker-compose.yml b/swarm/docker-compose.yml index 302a72e..6765f97 100644 --- a/swarm/docker-compose.yml +++ b/swarm/docker-compose.yml @@ -10,8 +10,32 @@ services: privileged: true volumes: - /var/run/dbus:/var/run/dbus + logging: + driver: "json-file" + options: + max-size: "10m" + + server: + container_name: server + build: + context: . + dockerfile: Dockerfile.swarm_server + depends_on: + - networking + - drone_1 + - drone_2 + networks: + swarm: + ipv4_address: 172.18.0.2 + ports: + - "65001:65001" + logging: + driver: "json-file" + options: + max-size: "10m" drone_1: + container_name: drone_1 build: context: . dockerfile: Dockerfile.swarm_node @@ -20,8 +44,13 @@ services: networks: swarm: ipv4_address: 172.18.0.3 + logging: + driver: "json-file" + options: + max-size: "10m" drone_2: + container_name: drone_2 build: context: . dockerfile: Dockerfile.swarm_node @@ -30,6 +59,10 @@ services: networks: swarm: ipv4_address: 172.18.0.4 + logging: + driver: "json-file" + options: + max-size: "10m" networks: swarm: diff --git a/swarm/scripts/rpc/server.py b/swarm/scripts/rpc/server.py new file mode 100644 index 0000000..934d1db --- /dev/null +++ b/swarm/scripts/rpc/server.py @@ -0,0 +1,12 @@ +from jsonrpcserver import method, Result, serve, Success, Error + + +@method(name="exec") +def exec(command: str) -> str: + status = "OK" + print(command) + return Success(command) if status == "OK" else Error(1, command) + + +if __name__ == "__main__": + serve(port=65000) diff --git a/swarm/scripts/rpc/swarm_server.py b/swarm/scripts/rpc/swarm_server.py new file mode 100644 index 0000000..d9b842a --- /dev/null +++ b/swarm/scripts/rpc/swarm_server.py @@ -0,0 +1,20 @@ +from jsonrpcserver import method, Result, serve, Success, Error +from jsonrpcclient import request +import requests + + +SWARM = ["drone_1", "drone_2"] + + +@method(name="exec") +def exec(command: str) -> str: + for node in SWARM: + url = f"http://{node}:65000" + req = request(url, "exec", command) + response = requests.post(url, json=req) + print(f"RESULT for '{url}' : {response}") + return Success("OK") + + +if __name__ == "__main__": + serve(port=65001) From d4962e117c4c22d7f08c72ee0946c1b899ab7d26 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Thu, 25 Apr 2024 18:59:04 +0300 Subject: [PATCH 49/72] added client application --- swarm/scripts/rpc/client.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 swarm/scripts/rpc/client.py diff --git a/swarm/scripts/rpc/client.py b/swarm/scripts/rpc/client.py new file mode 100644 index 0000000..58864a0 --- /dev/null +++ b/swarm/scripts/rpc/client.py @@ -0,0 +1,32 @@ +import argparse +import requests +from jsonrpcclient import request + + +def main(): + """ + CLI application to read a command from the user. + """ + parser = argparse.ArgumentParser( + description='CLI application to read a command') + parser.add_argument('-c', '--command', type=str, help='Command to execute') + parser.add_argument('--ip', type=str, help='IP address') + args = parser.parse_args() + + if args.command: + print(f'Executing command: {args.command}') + if args.ip: + print(f'IP Address: {args.ip}') + url = "http://" + {args.ip} + ":65001" + + req = request(url, "exec", args.command) + response = requests.post(url, json=req) + print(f"RESULT for '{url}' : {response.json()}") + else: + print('No IP address provided.') + else: + print('You need to pass the --command argument with a command to execute.') + + +if __name__ == "__main__": + main() From b789da18bc2d208774b20a100e618623b55ae830 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Thu, 25 Apr 2024 19:42:31 +0300 Subject: [PATCH 50/72] fixing secrets --- requirements.txt | 3 + swarm/scripts/rpc/server.py | 13 ++- swarm/scripts/rpc/swarm_server.py | 12 +-- wiki/swarm.md | 137 ++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 wiki/swarm.md diff --git a/requirements.txt b/requirements.txt index 8eb64a9..b030f3e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,6 @@ wifi netifaces docker loguru +jsonrpcclient +jsonrpcserver +requests \ No newline at end of file diff --git a/swarm/scripts/rpc/server.py b/swarm/scripts/rpc/server.py index 934d1db..d506f7f 100644 --- a/swarm/scripts/rpc/server.py +++ b/swarm/scripts/rpc/server.py @@ -1,12 +1,17 @@ -from jsonrpcserver import method, Result, serve, Success, Error - +from jsonrpcserver import method, Success, Error, serve @method(name="exec") def exec(command: str) -> str: - status = "OK" + """ + JSON-RPC method to execute a command. + """ + status = "OK" # Simulate command execution status + + # Print the command received print(command) - return Success(command) if status == "OK" else Error(1, command) + # Return success or error response based on status + return Success(command) if status == "OK" else Error(1, command) if __name__ == "__main__": serve(port=65000) diff --git a/swarm/scripts/rpc/swarm_server.py b/swarm/scripts/rpc/swarm_server.py index d9b842a..06f19ef 100644 --- a/swarm/scripts/rpc/swarm_server.py +++ b/swarm/scripts/rpc/swarm_server.py @@ -1,20 +1,22 @@ -from jsonrpcserver import method, Result, serve, Success, Error +from jsonrpcserver import method, Success, serve from jsonrpcclient import request import requests - -SWARM = ["drone_1", "drone_2"] - +SWARM = ["drone_1", "drone_2"] # List of drones in the swarm @method(name="exec") def exec(command: str) -> str: + """ + JSON-RPC method to execute a command on all drones in the swarm. + """ for node in SWARM: url = f"http://{node}:65000" req = request(url, "exec", command) response = requests.post(url, json=req) print(f"RESULT for '{url}' : {response}") - return Success("OK") + # Return success response + return Success("OK") if __name__ == "__main__": serve(port=65001) diff --git a/wiki/swarm.md b/wiki/swarm.md new file mode 100644 index 0000000..a7bd1b5 --- /dev/null +++ b/wiki/swarm.md @@ -0,0 +1,137 @@ +# Swarm + +This project consists of three Python scripts: client.py, server.py, and swarm_server.py. + +## client.py + +This script is a CLI application that sends commands to a JSON-RPC server. It accepts two command-line arguments: +- -c or --command: The command to execute. +- --ip: The IP address of the JSON-RPC server. + +> Example usage: +python client.py -c "ls -l" --ip "127.0.0.1" + +## server.py + +This script implements a JSON-RPC server with a single method exec, which executes the provided command. + +**Method exec:** +- Description: + - Executes the provided command. +- Parameters: + - command (str): The command to execute. +- Returns: + - str: The executed command. + +**Request:** +```json +{ + "jsonrpc": "2.0", + "method": "exec", + "params": { + "command": "takeoff" + }, + "id": 1 +} +``` +**Response:** +```json + { + "jsonrpc": "2.0", + "result": "OK", + "id": 1 + } +``` +# swarm_server.py + +This script implements a JSON-RPC server similar to server.py, but it is designed to work in a swarm environment. It executes the provided command on all drones in the swarm. + +**Method exec:** +- Description: Executes the provided command on all drones in the swarm. +- Parameters: + - command (str): The command to execute. +- Returns: + - str: The status of the execution. + +**Request:** +```json + { + "jsonrpc": "2.0", + "method": "exec", + "params": { + "command": "ls -l" + }, + "id": 1 + } +``` +**Response:** +```json + { + "jsonrpc": "2.0", + "result": "OK", + "id": 1 + } +``` + +# networking.py - Networking Class + +Class for configuring network and routing based on a JSON configuration file. + +## Attributes +- `PORTS` (list): List of ports for routing. + +## Methods + +### \_\_init\_\_(config: dict) +Initializes the Networking class object. + +**Parameters:** +- `config` (dict): Network configuration in dictionary format. + +### \_\_connection(config: dict) +Establishes connection to Wi-Fi networks specified in the configuration. + +**Parameters:** +- `config` (dict): Network configuration in dictionary format. + +### \_\_routing(iface: str, port: int, ip: str) +Configures routing for a specific network interface, port, and IP address. + +**Parameters:** +- `iface` (str): Network interface. +- `port` (int): Port for routing. +- `ip` (str): IP address for routing. + +## read_network_configuration(json_path: str) -> dict +Reads and validates the network configuration from a JSON file. + +**Parameters:** +- `json_path` (str): Path to the JSON file containing the network configuration. + +**Returns:** +- dict: Network configuration in dictionary format. + +## main(json_path: str) +Main function of the program. + +**Parameters:** +- `json_path` (str): Path to the JSON file containing the network configuration. + + +# Docker Files and Docker Compose + +## Dockerfile.networking + +This Dockerfile is used to build the networking container. It installs necessary networking tools and sets up the environment for networking.py. + +## Dockerfile.swarm_node + +This Dockerfile is used to build a swarm node container. It installs Python and the required dependencies for JSON-RPC server. + +## Dockerfile.swarm_server + +This Dockerfile is used to build the swarm server container. It installs Python and the required dependencies for JSON-RPC server, JSON-RPC client, and requests library. + +## docker-compose.yml + +This Docker Compose file defines the services required for the JSON-RPC application. It includes the networking service, server service, and two drone services. The networking service is configured to run with host network mode and provide necessary network functionalities for the application. The server service is configured to depend on the networking service and two drone services. It exposes port 65001 for external access. The drone services are configured to depend on the networking service and provide IP addresses for the swarm network. From 89788576ac8b48d73853a4e114aa4452b9ab432e Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Thu, 25 Apr 2024 21:12:59 +0300 Subject: [PATCH 51/72] fixed client app --- swarm/scripts/rpc/client.py | 9 +++------ swarm/scripts/rpc/swarm_server.py | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/swarm/scripts/rpc/client.py b/swarm/scripts/rpc/client.py index 58864a0..4c4e054 100644 --- a/swarm/scripts/rpc/client.py +++ b/swarm/scripts/rpc/client.py @@ -14,14 +14,11 @@ def main(): args = parser.parse_args() if args.command: - print(f'Executing command: {args.command}') if args.ip: - print(f'IP Address: {args.ip}') - url = "http://" + {args.ip} + ":65001" - - req = request(url, "exec", args.command) + url = f"http://{args.ip}:65001" + req = request("exec", params={ "command": args.command} ) response = requests.post(url, json=req) - print(f"RESULT for '{url}' : {response.json()}") + print(f"RESULT for '{url}' :\n\t {response.json()}") else: print('No IP address provided.') else: diff --git a/swarm/scripts/rpc/swarm_server.py b/swarm/scripts/rpc/swarm_server.py index 06f19ef..44af7f8 100644 --- a/swarm/scripts/rpc/swarm_server.py +++ b/swarm/scripts/rpc/swarm_server.py @@ -11,7 +11,7 @@ def exec(command: str) -> str: """ for node in SWARM: url = f"http://{node}:65000" - req = request(url, "exec", command) + req = request("exec", command) response = requests.post(url, json=req) print(f"RESULT for '{url}' : {response}") From 57b930ea389307ae20457ae06611e523cda864a1 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Thu, 25 Apr 2024 23:29:09 +0300 Subject: [PATCH 52/72] The Latest Version of controlls --- run_singel_drone.py | 2 +- swarm/scripts/solutions/following/config.py | 8 +++++--- .../solutions/following/follow_marker_coords.py | 14 +++++--------- swarm/scripts/solutions/following/state.py | 2 +- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/run_singel_drone.py b/run_singel_drone.py index b7d91c6..a22a9c1 100644 --- a/run_singel_drone.py +++ b/run_singel_drone.py @@ -1,4 +1,4 @@ -from swarm.scripts.solutions.following.follow_marker_coords import FollowMarkerWithCoords +from swarm.scripts.solutions.following.swarm_controlls import FollowMarkerWithCoords if __name__ == "__main__": marker_follower = FollowMarkerWithCoords() diff --git a/swarm/scripts/solutions/following/config.py b/swarm/scripts/solutions/following/config.py index de91aba..9538e89 100644 --- a/swarm/scripts/solutions/following/config.py +++ b/swarm/scripts/solutions/following/config.py @@ -5,17 +5,19 @@ FRAME_SIZE = (960, 720) MARKER_SIZE = 50 # in pixels MARKER_SIZE_RANGE = 15 +MARKER_NUMBER = 304 MARKER_CENTER = 304 -MARKER_STOP = 303 # random -MARKER_MOVE = 302 # random +MARKER_STOP = 305 # random +MARKER_MOVE = 301 # random X_RANGE = 125 Y_RANGE = 125 -TIMEOUT = 10 +TIMEOUT = 20 STEP = 25 Z_STEP = 25 SPEED = 50 QUEUE_SIZE = 100 MARKER_LEN = 6.5 +ROTATE_DEGREE = 45 camera_matrix, camera_distortion = load_camera_settings() diff --git a/swarm/scripts/solutions/following/follow_marker_coords.py b/swarm/scripts/solutions/following/follow_marker_coords.py index 62f98bc..6783b77 100644 --- a/swarm/scripts/solutions/following/follow_marker_coords.py +++ b/swarm/scripts/solutions/following/follow_marker_coords.py @@ -5,7 +5,7 @@ from queue import Queue, Empty from drone.drone import Drone from swarm.scripts.solutions.following.config import FRAME_RATE, FRAME_SIZE, DISTANCE, DISTANCE_RANGE,\ - ARUCO_DICT, ARUCO_PARAMS, QUEUE_SIZE, TIMEOUT, MARKER_CENTER, MARKER_MOVE, MARKER_STOP, SPEED + ARUCO_DICT, ARUCO_PARAMS, QUEUE_SIZE, TIMEOUT, MARKER_NUMBER, SPEED from swarm.scripts.solutions.following.config import camera_matrix, camera_distortion, MARKER_LEN from swarm.scripts.solutions.following.state import State from utils.write_text import write_status_on_image @@ -32,9 +32,9 @@ def get_state(self, tvec): marker_x, marker_y, marker_z = tvec[2], tvec[0], tvec[1] x = y = z = 0 if abs(marker_y) > 20: - y = -int(marker_y) if marker_y < 0 else 20 + y = -int(marker_y) if abs(marker_z) > 20: - z = -int(marker_z) if marker_z < 0 else 20 + z = -int(marker_z) if abs(marker_x - DISTANCE) > DISTANCE_RANGE: x = int(marker_x - DISTANCE) if x == 0 and y == 0 and z == 0: @@ -45,17 +45,13 @@ def find_marker(self, frame): corners, ids, rejected = cv2.aruco.detectMarkers(frame, ARUCO_DICT, parameters=ARUCO_PARAMS) if ids is not None: for i in range(len(ids)): - if ids[i] == MARKER_CENTER: - return (ids[i], corners[i]) - if ids[i] == MARKER_STOP: - return (ids[i], corners[i]) - if ids[i] == MARKER_MOVE: + if ids[i] == MARKER_NUMBER: return (ids[i], corners[i]) return None def move_to_marker(self, m_corner): self.last_time = time.process_time() - _ , rvecs, tvecs = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) + rvecs , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) state = self.get_state(tvecs[0][0]) if state == State.MOVE: self.actions.put(state) diff --git a/swarm/scripts/solutions/following/state.py b/swarm/scripts/solutions/following/state.py index 8f5b4d4..01f5dca 100644 --- a/swarm/scripts/solutions/following/state.py +++ b/swarm/scripts/solutions/following/state.py @@ -2,8 +2,8 @@ class State(Enum): + START = auto() END = auto() READY = auto() - START = auto() MOVE = auto() ROTATE = auto() \ No newline at end of file From f437611dd46651bf33065a0d7356b2365f9e2498 Mon Sep 17 00:00:00 2001 From: elcstazi Date: Thu, 25 Apr 2024 23:35:37 +0300 Subject: [PATCH 53/72] main controlls code --- .../solutions/following/swarm_controlls.py | 223 ++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 swarm/scripts/solutions/following/swarm_controlls.py diff --git a/swarm/scripts/solutions/following/swarm_controlls.py b/swarm/scripts/solutions/following/swarm_controlls.py new file mode 100644 index 0000000..f3fbc43 --- /dev/null +++ b/swarm/scripts/solutions/following/swarm_controlls.py @@ -0,0 +1,223 @@ +import docker +import os +import cv2 +import time +import math +import numpy as np +from queue import Queue, Empty +from drone.drone import Drone +from swarm.scripts.solutions.following.config import FRAME_RATE, FRAME_SIZE, DISTANCE, DISTANCE_RANGE,\ + ARUCO_DICT, ARUCO_PARAMS, QUEUE_SIZE, TIMEOUT, MARKER_CENTER, ROTATE_DEGREE, MARKER_MOVE, MARKER_STOP, SPEED +from swarm.scripts.solutions.following.config import camera_matrix, camera_distortion, MARKER_LEN +from swarm.scripts.solutions.following.state import State +from utils.write_text import write_status_on_image + +def dist_beetwen_points(p1, p2): + return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) + + +class FollowMarkerWithCoords(): + + def __init__(self): + self.video_writer = cv2.VideoWriter('drone_stream.avi', cv2.VideoWriter_fourcc(*'XVID'), FRAME_RATE, FRAME_SIZE) + self.actions = Queue(QUEUE_SIZE) + self.last_state = State.START + self.last_time = time.process_time() + self.last_battery_charge = 0 + self.is_stopped = False + self.num_of_rotates = 0 + self.flag = 0 + self.flag_two = 0 + # self.drone_id = None + # self.get_drone_id() + self.drone_id = 1 + self.coord_drone = None + self.num_of_rotate = 0 + + def stop(self): + self.is_stopped = True + + + + + def find_marker(self, frame): + corners, ids, rejected = cv2.aruco.detectMarkers(frame, ARUCO_DICT, parameters=ARUCO_PARAMS) + if ids is not None: + for i in range(len(ids)): + if ids[i] == MARKER_CENTER: + return (ids[i], corners[i]) + if ids[i] == MARKER_STOP: + return (ids[i], corners[i]) + if ids[i] == MARKER_MOVE: + return (ids[i], corners[i]) + return None + + def make_action(self, m_corner): + self.last_time = time.process_time() + rvecs , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) + state = self.get_state(tvecs[0][0]) + if state == State.MOVE: + self.actions.put(state) + self.last_state = state + + def marker_coords(self, m_corner, marker_id): + self.last_time = time.process_time() + _ , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, + camera_distortion) + tvec = tvecs[0][0] + marker_x, marker_y, marker_z = tvec[2], tvec[0], tvec[1] + x = z = y = 0 + drone_x = x + marker_x + drone_y = y + marker_y + drone_z = z + marker_z + print(drone_x,drone_y,drone_x) + angle_radians = math.radians(self.num_of_rotates) + + # Преобразуем угол поворота в матрицу поворота + R = np.array([[np.cos(angle_radians), -np.sin(angle_radians), 0], + [np.sin(angle_radians), np.cos(angle_radians), 0], + [0, 0, 1]]) + + # Исходные координаты дрона + drone_coords = np.array([drone_x, drone_y, drone_z]) + + # Применяем поворот к координатам дрона + rotated_coords = np.dot(R, drone_coords) + + # Добавляем координаты нулевой позиции дрона + drone_x_zero = int(rotated_coords[0]) + drone_y_zero = int(rotated_coords[1]) + drone_z_zero = int(rotated_coords[2]) + + # Добавляем смещение для учета положения дрона относительно маркера + if marker_id == MARKER_CENTER: + x = y = z = 0 # may be z = 50 + x = x + drone_x_zero + y = y + drone_y_zero + z = z + drone_z_zero + self.coord_drone = (x,y,z) + print(f"{self.drone_id}, {x}, {y}, {z}\n") + self.save_drone_info(f"{self.drone_id}, {x}, {y}, {z}\n") + elif marker_id == MARKER_MOVE: + x = y = z = 0 # may be z = 50 + x = x + drone_x_zero + self.coord_drone[0] + y = y + drone_y_zero + self.coord_drone[1] + z = z + drone_z_zero + self.coord_drone[2] + self.save_drone_info(f"MARKER_MOVE, {x}, {y}, {z}\n") + return 0 + + def save_drone_info(self, string): + try: + with open(".\drone_flight_logs.txt", 'a') as file: + file.write(string) + print(f"Координаты успешно сохранены в файл drone_flight_logs.txt") + return True + except Exception as e: + print(f"Ошибка при сохранении координат: {e}") + return False + + def process_frame(self, frame): + ids = None + is_find = True + if self.last_state == State.READY: + print("State.READY") + ret = self.find_marker(frame) + if ret is not None: + print("МАРКЕР НАЙДЕН") + marker_id, marker_corner = ret + print(marker_id) + frame = cv2.aruco.drawDetectedMarkers(frame, np.array([marker_corner]), np.array([marker_id])) + if marker_id == MARKER_CENTER and not self.flag: + print("Send COORDS") + self.marker_coords(marker_corner, MARKER_CENTER) + self.flag = 1 + print("START LINE COORDS") + print("degree rotate - ",self.num_of_rotates) + # i=1 + # for _ in range(self.num_of_rotates, 360, 45): + self.num_of_rotate = 360 - self.num_of_rotates + self.actions.put((State.ROTATE, None)) + # print(i) + # i+=1 + + # self.num_of_rotates = 0 + print("END LINE COORDS") + + if self.flag == 1: + if marker_id == MARKER_MOVE: + self.marker_coords(marker_corner, MARKER_MOVE) + state = self.move_to_marker() + self.actions.put(state) + self.last_state = state + + if marker_id == MARKER_STOP: + print("Send END") + self.actions.put((State.END, None)) + self.last_state = State.END + if marker_id == MARKER_CENTER: + print("Send ROTATE 2") + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + else: + print("Send ROTATE 2") + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + else: + # if not self.flag: + print("Send ROTATE 1") + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + if time.process_time() - self.last_time > TIMEOUT: + print("Send END2") + self.actions.put((State.END, None)) + self.last_state = State.END + # time.sleep(1.5) + write_status_on_image(frame, {"Battery": f"{self.last_battery_charge}%", "Last state": self.last_state}) + self.video_writer.write(cv2.resize(frame, FRAME_SIZE)) + return frame + + def drone_instructions(self, tello): + tello.takeoff() + # tello.move_up(50) + self.last_time = time.process_time() + self.last_state = State.READY + # x = z = y = tello.get_current_xyz() + + while not self.is_stopped: + try: + state, movements = self.actions.get(block=False, timeout=0.25) + self.actions.task_done() + if state == State.END: + break + elif state == State.MOVE: + # print("DO MOVE") + x, y, z = movements + print(movements) + tello.go_xyz_speed(int(x), int(y), int(z), SPEED) + elif state == State.ROTATE: + if self.num_of_rotate == 0: + + if self.num_of_rotates < 360: + x = ROTATE_DEGREE + tello.rotate_clockwise(x) + self.num_of_rotates += x + print("Rotate Degree", self.num_of_rotates) + else: + x = self.num_of_rotate + tello.rotate_clockwise(x) + self.num_of_rotate = 0 + print("Rotate on first pose", self.num_of_rotate) + self.num_of_rotates = 0 + + + + except Empty: + self.last_state = State.READY + self.last_battery_charge = tello.get_battery() + tello.land() + + def main(self): + self.is_stopped = False + drone = Drone(self.drone_instructions, self.process_frame, show_stream=True) + drone.run_program() + self.video_writer.release() \ No newline at end of file From 42ada2f5590bcf692ab15f42976ac29659ee22b5 Mon Sep 17 00:00:00 2001 From: Grigory_Tokun <90797638+TokGrin@users.noreply.github.com> Date: Thu, 25 Apr 2024 23:39:06 +0300 Subject: [PATCH 54/72] Delete swarm/scripts/solutions/following/swarm_controlls.py --- .../solutions/following/swarm_controlls.py | 223 ------------------ 1 file changed, 223 deletions(-) delete mode 100644 swarm/scripts/solutions/following/swarm_controlls.py diff --git a/swarm/scripts/solutions/following/swarm_controlls.py b/swarm/scripts/solutions/following/swarm_controlls.py deleted file mode 100644 index f3fbc43..0000000 --- a/swarm/scripts/solutions/following/swarm_controlls.py +++ /dev/null @@ -1,223 +0,0 @@ -import docker -import os -import cv2 -import time -import math -import numpy as np -from queue import Queue, Empty -from drone.drone import Drone -from swarm.scripts.solutions.following.config import FRAME_RATE, FRAME_SIZE, DISTANCE, DISTANCE_RANGE,\ - ARUCO_DICT, ARUCO_PARAMS, QUEUE_SIZE, TIMEOUT, MARKER_CENTER, ROTATE_DEGREE, MARKER_MOVE, MARKER_STOP, SPEED -from swarm.scripts.solutions.following.config import camera_matrix, camera_distortion, MARKER_LEN -from swarm.scripts.solutions.following.state import State -from utils.write_text import write_status_on_image - -def dist_beetwen_points(p1, p2): - return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) - - -class FollowMarkerWithCoords(): - - def __init__(self): - self.video_writer = cv2.VideoWriter('drone_stream.avi', cv2.VideoWriter_fourcc(*'XVID'), FRAME_RATE, FRAME_SIZE) - self.actions = Queue(QUEUE_SIZE) - self.last_state = State.START - self.last_time = time.process_time() - self.last_battery_charge = 0 - self.is_stopped = False - self.num_of_rotates = 0 - self.flag = 0 - self.flag_two = 0 - # self.drone_id = None - # self.get_drone_id() - self.drone_id = 1 - self.coord_drone = None - self.num_of_rotate = 0 - - def stop(self): - self.is_stopped = True - - - - - def find_marker(self, frame): - corners, ids, rejected = cv2.aruco.detectMarkers(frame, ARUCO_DICT, parameters=ARUCO_PARAMS) - if ids is not None: - for i in range(len(ids)): - if ids[i] == MARKER_CENTER: - return (ids[i], corners[i]) - if ids[i] == MARKER_STOP: - return (ids[i], corners[i]) - if ids[i] == MARKER_MOVE: - return (ids[i], corners[i]) - return None - - def make_action(self, m_corner): - self.last_time = time.process_time() - rvecs , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) - state = self.get_state(tvecs[0][0]) - if state == State.MOVE: - self.actions.put(state) - self.last_state = state - - def marker_coords(self, m_corner, marker_id): - self.last_time = time.process_time() - _ , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, - camera_distortion) - tvec = tvecs[0][0] - marker_x, marker_y, marker_z = tvec[2], tvec[0], tvec[1] - x = z = y = 0 - drone_x = x + marker_x - drone_y = y + marker_y - drone_z = z + marker_z - print(drone_x,drone_y,drone_x) - angle_radians = math.radians(self.num_of_rotates) - - # Преобразуем угол поворота в матрицу поворота - R = np.array([[np.cos(angle_radians), -np.sin(angle_radians), 0], - [np.sin(angle_radians), np.cos(angle_radians), 0], - [0, 0, 1]]) - - # Исходные координаты дрона - drone_coords = np.array([drone_x, drone_y, drone_z]) - - # Применяем поворот к координатам дрона - rotated_coords = np.dot(R, drone_coords) - - # Добавляем координаты нулевой позиции дрона - drone_x_zero = int(rotated_coords[0]) - drone_y_zero = int(rotated_coords[1]) - drone_z_zero = int(rotated_coords[2]) - - # Добавляем смещение для учета положения дрона относительно маркера - if marker_id == MARKER_CENTER: - x = y = z = 0 # may be z = 50 - x = x + drone_x_zero - y = y + drone_y_zero - z = z + drone_z_zero - self.coord_drone = (x,y,z) - print(f"{self.drone_id}, {x}, {y}, {z}\n") - self.save_drone_info(f"{self.drone_id}, {x}, {y}, {z}\n") - elif marker_id == MARKER_MOVE: - x = y = z = 0 # may be z = 50 - x = x + drone_x_zero + self.coord_drone[0] - y = y + drone_y_zero + self.coord_drone[1] - z = z + drone_z_zero + self.coord_drone[2] - self.save_drone_info(f"MARKER_MOVE, {x}, {y}, {z}\n") - return 0 - - def save_drone_info(self, string): - try: - with open(".\drone_flight_logs.txt", 'a') as file: - file.write(string) - print(f"Координаты успешно сохранены в файл drone_flight_logs.txt") - return True - except Exception as e: - print(f"Ошибка при сохранении координат: {e}") - return False - - def process_frame(self, frame): - ids = None - is_find = True - if self.last_state == State.READY: - print("State.READY") - ret = self.find_marker(frame) - if ret is not None: - print("МАРКЕР НАЙДЕН") - marker_id, marker_corner = ret - print(marker_id) - frame = cv2.aruco.drawDetectedMarkers(frame, np.array([marker_corner]), np.array([marker_id])) - if marker_id == MARKER_CENTER and not self.flag: - print("Send COORDS") - self.marker_coords(marker_corner, MARKER_CENTER) - self.flag = 1 - print("START LINE COORDS") - print("degree rotate - ",self.num_of_rotates) - # i=1 - # for _ in range(self.num_of_rotates, 360, 45): - self.num_of_rotate = 360 - self.num_of_rotates - self.actions.put((State.ROTATE, None)) - # print(i) - # i+=1 - - # self.num_of_rotates = 0 - print("END LINE COORDS") - - if self.flag == 1: - if marker_id == MARKER_MOVE: - self.marker_coords(marker_corner, MARKER_MOVE) - state = self.move_to_marker() - self.actions.put(state) - self.last_state = state - - if marker_id == MARKER_STOP: - print("Send END") - self.actions.put((State.END, None)) - self.last_state = State.END - if marker_id == MARKER_CENTER: - print("Send ROTATE 2") - self.actions.put((State.ROTATE, None)) - self.last_state = State.ROTATE - else: - print("Send ROTATE 2") - self.actions.put((State.ROTATE, None)) - self.last_state = State.ROTATE - else: - # if not self.flag: - print("Send ROTATE 1") - self.actions.put((State.ROTATE, None)) - self.last_state = State.ROTATE - if time.process_time() - self.last_time > TIMEOUT: - print("Send END2") - self.actions.put((State.END, None)) - self.last_state = State.END - # time.sleep(1.5) - write_status_on_image(frame, {"Battery": f"{self.last_battery_charge}%", "Last state": self.last_state}) - self.video_writer.write(cv2.resize(frame, FRAME_SIZE)) - return frame - - def drone_instructions(self, tello): - tello.takeoff() - # tello.move_up(50) - self.last_time = time.process_time() - self.last_state = State.READY - # x = z = y = tello.get_current_xyz() - - while not self.is_stopped: - try: - state, movements = self.actions.get(block=False, timeout=0.25) - self.actions.task_done() - if state == State.END: - break - elif state == State.MOVE: - # print("DO MOVE") - x, y, z = movements - print(movements) - tello.go_xyz_speed(int(x), int(y), int(z), SPEED) - elif state == State.ROTATE: - if self.num_of_rotate == 0: - - if self.num_of_rotates < 360: - x = ROTATE_DEGREE - tello.rotate_clockwise(x) - self.num_of_rotates += x - print("Rotate Degree", self.num_of_rotates) - else: - x = self.num_of_rotate - tello.rotate_clockwise(x) - self.num_of_rotate = 0 - print("Rotate on first pose", self.num_of_rotate) - self.num_of_rotates = 0 - - - - except Empty: - self.last_state = State.READY - self.last_battery_charge = tello.get_battery() - tello.land() - - def main(self): - self.is_stopped = False - drone = Drone(self.drone_instructions, self.process_frame, show_stream=True) - drone.run_program() - self.video_writer.release() \ No newline at end of file From 2a801a48e7df2c99da4d18ad23f4b04ab624f1c0 Mon Sep 17 00:00:00 2001 From: elcstazi Date: Fri, 26 Apr 2024 00:19:39 +0300 Subject: [PATCH 55/72] control of a single drone without approach --- .../solutions/following/swarm_controlls.py | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 swarm/scripts/solutions/following/swarm_controlls.py diff --git a/swarm/scripts/solutions/following/swarm_controlls.py b/swarm/scripts/solutions/following/swarm_controlls.py new file mode 100644 index 0000000..65732bd --- /dev/null +++ b/swarm/scripts/solutions/following/swarm_controlls.py @@ -0,0 +1,175 @@ +import docker +import os +import cv2 +import time +import math +import numpy as np +from queue import Queue, Empty +from drone.drone import Drone +from swarm.scripts.solutions.following.config import FRAME_RATE, FRAME_SIZE, DISTANCE, DISTANCE_RANGE,\ + ARUCO_DICT, ARUCO_PARAMS, QUEUE_SIZE, TIMEOUT, MARKER_CENTER, ROTATE_DEGREE, MARKER_MOVE, MARKER_STOP, SPEED +from swarm.scripts.solutions.following.config import camera_matrix, camera_distortion, MARKER_LEN +from swarm.scripts.solutions.following.state import State +from utils.write_text import write_status_on_image + +def dist_beetwen_points(p1, p2): + return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) + + +class FollowMarkerWithCoords(): + + def __init__(self): + self.video_writer = cv2.VideoWriter('drone_stream.avi', cv2.VideoWriter_fourcc(*'XVID'), FRAME_RATE, FRAME_SIZE) + self.actions = Queue(QUEUE_SIZE) + self.last_state = State.START + self.last_time = time.process_time() + self.last_battery_charge = 0 + self.is_stopped = False + self.num_of_rotates = 0 + self.flag = 0 + self.flag_two = 0 + # self.drone_id = None + # self.get_drone_id() + self.drone_id = 1 + self.coord_drone = None + self.num_of_rotate = 0 + + def stop(self): + self.is_stopped = True + + # def get_drone_id(self): + # client = docker.client.from_env() + # self.drone_id = os.environ.get('HOSTNAME') + # if not self.drone_id: + # self.drone_id = -1 + + + + + def find_marker(self, frame): + corners, ids, rejected = cv2.aruco.detectMarkers(frame, ARUCO_DICT, parameters=ARUCO_PARAMS) + if ids is not None: + for i in range(len(ids)): + if ids[i] == MARKER_CENTER: + return (ids[i], corners[i]) + if ids[i] == MARKER_STOP: + return (ids[i], corners[i]) + if ids[i] == MARKER_MOVE: + return (ids[i], corners[i]) + return None + + def make_action(self, m_corner): + self.last_time = time.process_time() + rvecs , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) + state = self.get_state(tvecs[0][0]) + if state == State.MOVE: + self.actions.put(state) + self.last_state = state + + + + def process_frame(self, frame): + ids = None + is_find = True + if self.last_state == State.READY: + print("State.READY") + ret = self.find_marker(frame) + if ret is not None: + print("МАРКЕР НАЙДЕН") + marker_id, marker_corner = ret + print(marker_id) + frame = cv2.aruco.drawDetectedMarkers(frame, np.array([marker_corner]), np.array([marker_id])) + if marker_id == MARKER_CENTER and not self.flag: + print("Send COORDS") + self.marker_coords(marker_corner, MARKER_CENTER) + self.flag = 1 + print("START LINE COORDS") + print("degree rotate - ",self.num_of_rotates) + # i=1 + # for _ in range(self.num_of_rotates, 360, 45): + self.num_of_rotate = 360 - self.num_of_rotates + self.actions.put((State.ROTATE, None)) + # print(i) + # i+=1 + + # self.num_of_rotates = 0 + print("END LINE COORDS") + + if self.flag == 1: + if marker_id == MARKER_MOVE: + self.marker_coords(marker_corner, MARKER_MOVE) + state = self.move_to_marker() + self.actions.put(state) + self.last_state = state + + if marker_id == MARKER_STOP: + print("Send END") + self.actions.put((State.END, None)) + self.last_state = State.END + if marker_id == MARKER_CENTER: + print("Send ROTATE 2") + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + else: + print("Send ROTATE 2") + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + else: + # if not self.flag: + print("Send ROTATE 1") + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + if time.process_time() - self.last_time > TIMEOUT: + print("Send END2") + self.actions.put((State.END, None)) + self.last_state = State.END + # time.sleep(1.5) + write_status_on_image(frame, {"Battery": f"{self.last_battery_charge}%", "Last state": self.last_state}) + self.video_writer.write(cv2.resize(frame, FRAME_SIZE)) + return frame + + def drone_instructions(self, tello): + tello.takeoff() + # tello.move_up(50) + self.last_time = time.process_time() + self.last_state = State.READY + # x = z = y = tello.get_current_xyz() + + while not self.is_stopped: + try: + state, movements = self.actions.get(block=False, timeout=0.25) + self.actions.task_done() + if state == State.END: + break + elif state == State.MOVE: + # print("DO MOVE") + x, y, z = movements + print(movements) + tello.go_xyz_speed(int(x), int(y), int(z), SPEED) + elif state == State.ROTATE: + if self.num_of_rotate == 0: + + if self.num_of_rotates < 360: + x = ROTATE_DEGREE + tello.rotate_clockwise(x) + self.num_of_rotates += x + print("Rotate Degree", self.num_of_rotates) + else: + x = self.num_of_rotate + tello.rotate_clockwise(x) + self.num_of_rotate = 0 + print("Rotate on first pose", self.num_of_rotate) + self.num_of_rotates = 0 + + + + except Empty: + self.last_state = State.READY + self.last_battery_charge = tello.get_battery() + tello.land() + + def main(self): + self.is_stopped = False + drone = Drone(self.drone_instructions, self.process_frame, show_stream=True) + drone.run_program() + self.video_writer.release() \ No newline at end of file From 18d5f160b68713606fc56928a270e5b964594213 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Fri, 26 Apr 2024 01:26:40 +0300 Subject: [PATCH 56/72] functions to coordinate drones --- .../solutions/following/swarm_controlls.py | 49 +++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/swarm/scripts/solutions/following/swarm_controlls.py b/swarm/scripts/solutions/following/swarm_controlls.py index 65732bd..a2ad97b 100644 --- a/swarm/scripts/solutions/following/swarm_controlls.py +++ b/swarm/scripts/solutions/following/swarm_controlls.py @@ -43,8 +43,51 @@ def stop(self): # if not self.drone_id: # self.drone_id = -1 - - + def move_to_marker(self): + coordinates = {} + move_marker = None + try: + with open("drone_flight_logs.txt", 'r') as file: + lines = file.readlines() + for line in lines: + # Разделяем строку на координаты и преобразуем их в числа + target, x, y, z = map(float, line.strip().split(',')) + coordinates[target] = (x, y, z) # 1-3 dron_id, 4 - MARKER_MOVE, 5 - MARKER_STOP + if target == "MARKER_MOVE": + print(coordinates) + + print(f"Координаты успешно прочитаны из файла drone_flight_logs.txt") + except Exception as e: + print(f"Ошибка при чтении координат из файла: {e}") + + x, y, z = coordinates.get("MARKER_MOVE") + x_un = self.coord_drone[0] - x + y_un = self.coord_drone[1] - y + z_un = self.coord_drone[2] - z + self.coord_drone = (x_un, y_un, z_un) + coord_drone = (x_un, y_un, z_un) + angle_degrees = 360 - self.num_of_rotates + + # Получаем матрицу поворота из вектора ориентации + angle_radians = math.radians(angle_degrees) + + # Преобразуем угол поворота в матрицу поворота + R = np.array([[np.cos(angle_radians), -np.sin(angle_radians), 0], + [np.sin(angle_radians), np.cos(angle_radians), 0], + [0, 0, 1]]) + + # Исходные координаты дрона + drone_coords = np.array(coord_drone) + + # Применяем поворот к координатам дрона + rotated_coords = np.dot(R, drone_coords) + + # Добавляем координаты нулевой позиции дрона + x = int(rotated_coords[0] - 10) + y = int(rotated_coords[1]) + z = int(rotated_coords[2]) + + return (State.MOVE, np.array([x, y, z], dtype=np.int32)) def find_marker(self, frame): corners, ids, rejected = cv2.aruco.detectMarkers(frame, ARUCO_DICT, parameters=ARUCO_PARAMS) @@ -66,8 +109,6 @@ def make_action(self, m_corner): self.actions.put(state) self.last_state = state - - def process_frame(self, frame): ids = None is_find = True From c84f2da40653d267001e34dae5d750f513f8dcb6 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Fri, 26 Apr 2024 01:29:22 +0300 Subject: [PATCH 57/72] second func --- .../solutions/following/swarm_controlls.py | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/swarm/scripts/solutions/following/swarm_controlls.py b/swarm/scripts/solutions/following/swarm_controlls.py index a2ad97b..8fded52 100644 --- a/swarm/scripts/solutions/following/swarm_controlls.py +++ b/swarm/scripts/solutions/following/swarm_controlls.py @@ -109,6 +109,51 @@ def make_action(self, m_corner): self.actions.put(state) self.last_state = state + def marker_coords(self, m_corner, marker_id): + self.last_time = time.process_time() + _ , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, + camera_distortion) + tvec = tvecs[0][0] + marker_x, marker_y, marker_z = tvec[2], tvec[0], tvec[1] + x = z = y = 0 + drone_x = x + marker_x + drone_y = y + marker_y + drone_z = z + marker_z + print(drone_x,drone_y,drone_x) + angle_radians = math.radians(self.num_of_rotates) + + # Преобразуем угол поворота в матрицу поворота + R = np.array([[np.cos(angle_radians), -np.sin(angle_radians), 0], + [np.sin(angle_radians), np.cos(angle_radians), 0], + [0, 0, 1]]) + + # Исходные координаты дрона + drone_coords = np.array([drone_x, drone_y, drone_z]) + + # Применяем поворот к координатам дрона + rotated_coords = np.dot(R, drone_coords) + + # Добавляем координаты нулевой позиции дрона + drone_x_zero = int(rotated_coords[0]) + drone_y_zero = int(rotated_coords[1]) + drone_z_zero = int(rotated_coords[2]) + + # Добавляем смещение для учета положения дрона относительно маркера + if marker_id == MARKER_CENTER: + x = y = z = 0 # may be z = 50 + x = x + drone_x_zero + y = y + drone_y_zero + z = z + drone_z_zero + self.coord_drone = (x,y,z) + self.save_drone_info(f"{self.drone_id}, {x}, {y}, {z}\n") + elif marker_id == MARKER_MOVE: + x = y = z = 0 # may be z = 50 + x = x + drone_x_zero + self.coord_drone[0] + y = y + drone_y_zero + self.coord_drone[1] + z = z + drone_z_zero + self.coord_drone[2] + self.save_drone_info(f"MARKER_MOVE, {x}, {y}, {z}\n") + return 0 + def process_frame(self, frame): ids = None is_find = True From 705585896a14dd957225df6dfed61f244512e454 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Fri, 26 Apr 2024 01:45:08 +0300 Subject: [PATCH 58/72] one forgotten func --- .../solutions/following/swarm_controlls.py | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/swarm/scripts/solutions/following/swarm_controlls.py b/swarm/scripts/solutions/following/swarm_controlls.py index 8fded52..c27b71b 100644 --- a/swarm/scripts/solutions/following/swarm_controlls.py +++ b/swarm/scripts/solutions/following/swarm_controlls.py @@ -103,7 +103,8 @@ def find_marker(self, frame): def make_action(self, m_corner): self.last_time = time.process_time() - rvecs , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) + rvecs, tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, + camera_distortion) state = self.get_state(tvecs[0][0]) if state == State.MOVE: self.actions.put(state) @@ -111,15 +112,15 @@ def make_action(self, m_corner): def marker_coords(self, m_corner, marker_id): self.last_time = time.process_time() - _ , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, - camera_distortion) + _, tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, + camera_distortion) tvec = tvecs[0][0] marker_x, marker_y, marker_z = tvec[2], tvec[0], tvec[1] x = z = y = 0 drone_x = x + marker_x drone_y = y + marker_y drone_z = z + marker_z - print(drone_x,drone_y,drone_x) + print(drone_x, drone_y, drone_x) angle_radians = math.radians(self.num_of_rotates) # Преобразуем угол поворота в матрицу поворота @@ -140,20 +141,31 @@ def marker_coords(self, m_corner, marker_id): # Добавляем смещение для учета положения дрона относительно маркера if marker_id == MARKER_CENTER: - x = y = z = 0 # may be z = 50 + x = y = z = 0 # may be z = 50 x = x + drone_x_zero y = y + drone_y_zero z = z + drone_z_zero - self.coord_drone = (x,y,z) + self.coord_drone = (x, y, z) + print(f"{self.drone_id}, {x}, {y}, {z}\n") self.save_drone_info(f"{self.drone_id}, {x}, {y}, {z}\n") elif marker_id == MARKER_MOVE: - x = y = z = 0 # may be z = 50 + x = y = z = 0 # may be z = 50 x = x + drone_x_zero + self.coord_drone[0] y = y + drone_y_zero + self.coord_drone[1] z = z + drone_z_zero + self.coord_drone[2] self.save_drone_info(f"MARKER_MOVE, {x}, {y}, {z}\n") return 0 + def save_drone_info(self, string): + try: + with open(".\drone_flight_logs.txt", 'a') as file: + file.write(string) + print(f"Координаты успешно сохранены в файл drone_flight_logs.txt") + return True + except Exception as e: + print(f"Ошибка при сохранении координат: {e}") + return False + def process_frame(self, frame): ids = None is_find = True From 2427413f797875e52a24b7ec4d0c7c16b6e50f7d Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Fri, 26 Apr 2024 03:52:57 +0300 Subject: [PATCH 59/72] Update README.md --- README.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/README.md b/README.md index c147abb..0df4d41 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,80 @@ +# Итерация 3 +Зависимости: +Версия ОС: Ubuntu 22.04.4 LTS +Python 3.10.12 + +## Конфигурирование +Заполнить [конфигурационный файл](https://github.com/OSLL/tello-dev/blob/master/swarm/networks.json) +```json +{ + "ifaces" : { + "iface-name" : { + "ssid" : "", + "password" : "", + "ip": "172.18.0.3" + }, + "iface-name": { + "ssid" : "", + "password" : "", + "ip": "172.18.0.4" + } + } +} +``` +- Необходимо выполнить команду `ip a` и вставить имена необходимых wlan-интерфейсов вместо `iface-name`. +- Установить пакет `network-manager`: + `apt install network-manager=1.36.6-0ubuntu2` +- Выполнить команду `nmcli dev wifi scan` и определить SSID wifi сетей причастных к дрону и вставить вместо `ssid` + +**Пример сконфигурированного файла** +```json +{ + "ifaces" : { + "wlo0" : { + "ssid" : "DRONE 1", + "password" : "", + "ip": "172.18.0.3" + }, + "wlo1": { + "ssid" : "DRONE 2", + "password" : "", + "ip": "172.18.0.4" + } + } +} +``` + +## Запуск +Установить зависимости +```bash +python3 -m pip install jsonrpcclient==4.0.3 requests==2.31.0 +``` +- Необходимо выполнить команду `docker compose -f ./swarm/docker-compose.yml up -d --build` (в одном месте монтируется с хоста папка и этого не избежать, иначе из контейнера нельзя будет управлять сетевыми устройствами) +- После запуска необходимо вызвать скрипт *client.py* передав флаги -c --ip , + где: + + --ip - P-адреса сервера JSON-RPC, к которому скрипт будет отправлять запросы, у нас это 127.0.0.1. + + -c - команда для дронов. + +Пример: +```bash +python3 ./swarm/scripts/rpc/client.py -c takeoff --ip 127.0.0.1 +``` +Результат: +```bash +RESULT for 'http://127.0.0.1:65001' : + {'jsonrpc': '2.0', 'result': 'OK', 'id': 1} +``` +## Презентация и видео +[Видео запуска из лаборатории](https://drive.google.com/file/d/1AlVOG27zfj0EoQd7CfunbafDo9c3x55g/view?usp=sharing) +[Логи запуска](https://drive.google.com/file/d/1QEGajXq3eJybhvswaCkATVJhRs7hSCsq/view?usp=sharing) +Презентация:[ОУПРПО. Итерация 3. Проект 12.pdf](https://github.com/OSLL/tello-dev/files/15123364/3.12.pdf) + + +# +# + # Итерация 2 ## Версия 1 Чтобы запустить рой из одного дрона [(wiki скрипта)](https://github.com/OSLL/tello-dev/wiki/%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D0%BE%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE-%D0%B4%D1%80%D0%BE%D0%BD%D0%B0), необходимо выполнить следующие команды: From 553533a82c30c2fa2e8e0efb298dbcd2c24e8048 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Fri, 26 Apr 2024 03:55:57 +0300 Subject: [PATCH 60/72] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0df4d41..484abb0 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ RESULT for 'http://127.0.0.1:65001' : ## Презентация и видео [Видео запуска из лаборатории](https://drive.google.com/file/d/1AlVOG27zfj0EoQd7CfunbafDo9c3x55g/view?usp=sharing) [Логи запуска](https://drive.google.com/file/d/1QEGajXq3eJybhvswaCkATVJhRs7hSCsq/view?usp=sharing) -Презентация:[ОУПРПО. Итерация 3. Проект 12.pdf](https://github.com/OSLL/tello-dev/files/15123364/3.12.pdf) +Презентация:[ОУПРПО. Итерация 3. Проект 12](https://drive.google.com/file/d/1SChuYAM4CD_IQHj4QtwAoYbMkWu40w0_/view?usp=sharing) # From e0544be25f328f47148a47c1e093f2de4bfbe588 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Fri, 26 Apr 2024 03:57:42 +0300 Subject: [PATCH 61/72] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 484abb0..6572af5 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Python 3.10.12 - Необходимо выполнить команду `ip a` и вставить имена необходимых wlan-интерфейсов вместо `iface-name`. - Установить пакет `network-manager`: `apt install network-manager=1.36.6-0ubuntu2` -- Выполнить команду `nmcli dev wifi scan` и определить SSID wifi сетей причастных к дрону и вставить вместо `ssid` +- Выполнить команду `nmcli dev wifi list` и определить SSID wifi сетей причастных к дрону и вставить вместо `ssid` **Пример сконфигурированного файла** ```json From 0181dfaa68718684081565106d5e1c753c5d73da Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Sun, 12 May 2024 17:04:54 +0300 Subject: [PATCH 62/72] Create main.yml --- .github/workflows/main.yml | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..ecd8ced --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,39 @@ +name: Docker CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Docker + uses: docker/setup-action@v2 + + - name: Build and run containers + run: | + docker-compose up -d + sleep 5 + docker ps + + - name: Check containers status + run: | + if docker ps | grep -q "droner"; then + echo "Containers are running successfully" + else + echo "Error occurred while running containers" + exit 1 + fi + + - name: Run tests + run: | + docker-compose -f path/to/your/docker-compose.yml exec -T your_service_name sh -c "your_test_script.sh" From 51be52db1952000be9cacf19679d515dc7c4c0d7 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Wed, 22 May 2024 19:48:30 +0300 Subject: [PATCH 63/72] changed network --- swarm/docker-compose.yml | 10 +++++----- swarm/networks.json | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/swarm/docker-compose.yml b/swarm/docker-compose.yml index 6765f97..d77332b 100644 --- a/swarm/docker-compose.yml +++ b/swarm/docker-compose.yml @@ -26,7 +26,7 @@ services: - drone_2 networks: swarm: - ipv4_address: 172.18.0.2 + ipv4_address: 172.230.220.2 ports: - "65001:65001" logging: @@ -43,7 +43,7 @@ services: - networking networks: swarm: - ipv4_address: 172.18.0.3 + ipv4_address: 172.230.220.3 logging: driver: "json-file" options: @@ -58,7 +58,7 @@ services: - networking networks: swarm: - ipv4_address: 172.18.0.4 + ipv4_address: 172.230.220.4 logging: driver: "json-file" options: @@ -69,5 +69,5 @@ networks: driver: bridge ipam: config: - - subnet: 172.18.0.0/16 - gateway: 172.18.0.1 \ No newline at end of file + - subnet: 172.230.220.0/24 + gateway: 172.230.220.1 \ No newline at end of file diff --git a/swarm/networks.json b/swarm/networks.json index decec15..c9318aa 100644 --- a/swarm/networks.json +++ b/swarm/networks.json @@ -3,12 +3,12 @@ "" : { "ssid" : "", "password" : "", - "ip": "172.18.0.3" + "ip": "172.230.220.3" }, "": { "ssid" : "", "password" : "", - "ip": "172.18.0.4" + "ip": "172.230.220.4" } } } From e62b12878565fe1a4b2265ff6fd76ec88d5e1fc6 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Wed, 22 May 2024 20:17:12 +0300 Subject: [PATCH 64/72] fixed version --- swarm/docker-compose.yml | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/swarm/docker-compose.yml b/swarm/docker-compose.yml index d77332b..b81a164 100644 --- a/swarm/docker-compose.yml +++ b/swarm/docker-compose.yml @@ -1,4 +1,3 @@ -version: "3" services: networking: build: @@ -11,9 +10,9 @@ services: volumes: - /var/run/dbus:/var/run/dbus logging: - driver: "json-file" + driver: "json-file" options: - max-size: "10m" + max-size: "10m" server: container_name: server @@ -30,10 +29,10 @@ services: ports: - "65001:65001" logging: - driver: "json-file" + driver: "json-file" options: - max-size: "10m" - + max-size: "10m" + drone_1: container_name: drone_1 build: @@ -45,9 +44,9 @@ services: swarm: ipv4_address: 172.230.220.3 logging: - driver: "json-file" + driver: "json-file" options: - max-size: "10m" + max-size: "10m" drone_2: container_name: drone_2 @@ -60,14 +59,14 @@ services: swarm: ipv4_address: 172.230.220.4 logging: - driver: "json-file" + driver: "json-file" options: - max-size: "10m" + max-size: "10m" networks: swarm: driver: bridge ipam: - config: - - subnet: 172.230.220.0/24 - gateway: 172.230.220.1 \ No newline at end of file + config: + - subnet: 172.230.220.0/24 + gateway: 172.230.220.1 From a1f16ab0c4eba265ae79f5bcba08fddbf2d22715 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Wed, 22 May 2024 21:33:31 +0300 Subject: [PATCH 65/72] specified versions --- swarm/Dockerfile.networking | 15 +++++++-------- swarm/Dockerfile.swarm_node | 6 +++--- swarm/Dockerfile.swarm_server | 6 +++--- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/swarm/Dockerfile.networking b/swarm/Dockerfile.networking index 8c7e57b..7aa4199 100644 --- a/swarm/Dockerfile.networking +++ b/swarm/Dockerfile.networking @@ -1,16 +1,15 @@ FROM ubuntu:22.04 -COPY /scripts/networking/localtime /etc/localtime +COPY /scripts/networking/localtime /etc/localtime RUN apt update \ && apt install -y \ - network-manager \ - iptables \ - netcat \ - tcpdump \ - iputils-ping \ - python3 \ - python3-pip + network-manager=1.36.6-0ubuntu2 \ + iptables=1.8.7-1ubuntu5.2 \ + python3=3.10.6-1~22.04 \ + python3-pip=22.0.2+dfsg-1ubuntu0.4 RUN pip install --upgrade jsonschema COPY /scripts/networking/networking.py /networking.py +COPY /scripts/rpc/server.py server.py +COPY /scripts/rpc/swarm_server.py swarm_server.py COPY /networks.json /networks.json ENTRYPOINT ["python3", "networking.py", "/networks.json"] \ No newline at end of file diff --git a/swarm/Dockerfile.swarm_node b/swarm/Dockerfile.swarm_node index db03de7..183ba9b 100644 --- a/swarm/Dockerfile.swarm_node +++ b/swarm/Dockerfile.swarm_node @@ -1,9 +1,9 @@ FROM ubuntu:22.04 RUN apt update \ && apt install -y \ - python3 \ - python3-pip \ - && pip install jsonrpcserver + python3=3.10.6-1~22.04 \ + python3-pip=22.0.2+dfsg-1ubuntu0.4 \ + && pip install jsonrpcserver==5.0.9 COPY /scripts/rpc/server.py server.py EXPOSE 65000 diff --git a/swarm/Dockerfile.swarm_server b/swarm/Dockerfile.swarm_server index 502329b..0d35331 100644 --- a/swarm/Dockerfile.swarm_server +++ b/swarm/Dockerfile.swarm_server @@ -1,9 +1,9 @@ FROM ubuntu:22.04 RUN apt update \ && apt install -y \ - python3 \ - python3-pip \ - && pip install jsonrpcserver jsonrpcclient requests + python3=3.10.6-1~22.04 \ + python3-pip=22.0.2+dfsg-1ubuntu0.4 \ + && pip install jsonrpcserver==5.0.9 jsonrpcclient==4.0.3 requests==2.32.2 COPY /scripts/rpc/swarm_server.py swarm_server.py EXPOSE 65001 From edc6a694ccb1b841eb5b4c26b30ff7a5cb4a98c1 Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Wed, 22 May 2024 21:45:18 +0300 Subject: [PATCH 66/72] merged dockerfiles --- swarm/Dockerfile | 31 +++++++++++++++++++++++++++++++ swarm/docker-compose.yml | 23 ++++++++++++++++------- swarm/entrypoint.sh | 16 ++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 swarm/Dockerfile create mode 100644 swarm/entrypoint.sh diff --git a/swarm/Dockerfile b/swarm/Dockerfile new file mode 100644 index 0000000..46f043d --- /dev/null +++ b/swarm/Dockerfile @@ -0,0 +1,31 @@ +FROM ubuntu:22.04 + +COPY /scripts/networking/localtime /etc/localtime + +# Общие зависимости +RUN apt update \ + && apt install -y \ + network-manager=1.36.6-0ubuntu2 \ + iptables=1.8.7-1ubuntu5.2 \ + python3=3.10.6-1~22.04 \ + python3-pip=22.0.2+dfsg-1ubuntu0.4 \ + && apt clean + +# Установка Python пакетов +RUN pip install --upgrade pip \ + && pip install jsonschema==4.22.0 \ + && pip install jsonrpcserver==5.0.9 \ + && pip install jsonrpcclient==4.0.3 requests==2.32.2 + +# Слои для каждого сервиса +COPY /scripts/networking/networking.py /networking.py +COPY /scripts/rpc/server.py /server.py +COPY /scripts/rpc/swarm_server.py /swarm_server.py +COPY /networks.json /networks.json + + +# Скрипт для запуска нужного сервиса на основе переменной среды +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/swarm/docker-compose.yml b/swarm/docker-compose.yml index b81a164..6e81569 100644 --- a/swarm/docker-compose.yml +++ b/swarm/docker-compose.yml @@ -1,24 +1,27 @@ +version: "3.8" services: networking: build: context: . - dockerfile: Dockerfile.networking + dockerfile: Dockerfile network_mode: "host" container_name: networking restart: no privileged: true volumes: - /var/run/dbus:/var/run/dbus + environment: + - SERVICE_NAME=networking logging: driver: "json-file" options: max-size: "10m" server: - container_name: server build: context: . - dockerfile: Dockerfile.swarm_server + dockerfile: Dockerfile + container_name: server depends_on: - networking - drone_1 @@ -28,36 +31,42 @@ services: ipv4_address: 172.230.220.2 ports: - "65001:65001" + environment: + - SERVICE_NAME=server logging: driver: "json-file" options: max-size: "10m" drone_1: - container_name: drone_1 build: context: . - dockerfile: Dockerfile.swarm_node + dockerfile: Dockerfile + container_name: drone_1 depends_on: - networking networks: swarm: ipv4_address: 172.230.220.3 + environment: + - SERVICE_NAME=swarm_server logging: driver: "json-file" options: max-size: "10m" drone_2: - container_name: drone_2 build: context: . - dockerfile: Dockerfile.swarm_node + dockerfile: Dockerfile + container_name: drone_2 depends_on: - networking networks: swarm: ipv4_address: 172.230.220.4 + environment: + - SERVICE_NAME=swarm_server logging: driver: "json-file" options: diff --git a/swarm/entrypoint.sh b/swarm/entrypoint.sh new file mode 100644 index 0000000..1d66884 --- /dev/null +++ b/swarm/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/sh +case "$SERVICE_NAME" in + networking) + exec python3 /networking.py /networks.json + ;; + server) + exec python3 /server.py + ;; + swarm_server) + exec python3 /swarm_server.py + ;; + *) + echo "Unknown service: $SERVICE_NAME" + exit 1 + ;; +esac From d7eaf0a61d562a8ec86af0a998d01e4a2ee383dc Mon Sep 17 00:00:00 2001 From: Evgeniy Lukin Date: Wed, 22 May 2024 21:46:45 +0300 Subject: [PATCH 67/72] deleted old dockerfiles --- swarm/Dockerfile.networking | 15 --------------- swarm/Dockerfile.swarm_node | 10 ---------- swarm/Dockerfile.swarm_server | 10 ---------- 3 files changed, 35 deletions(-) delete mode 100644 swarm/Dockerfile.networking delete mode 100644 swarm/Dockerfile.swarm_node delete mode 100644 swarm/Dockerfile.swarm_server diff --git a/swarm/Dockerfile.networking b/swarm/Dockerfile.networking deleted file mode 100644 index 7aa4199..0000000 --- a/swarm/Dockerfile.networking +++ /dev/null @@ -1,15 +0,0 @@ -FROM ubuntu:22.04 -COPY /scripts/networking/localtime /etc/localtime -RUN apt update \ - && apt install -y \ - network-manager=1.36.6-0ubuntu2 \ - iptables=1.8.7-1ubuntu5.2 \ - python3=3.10.6-1~22.04 \ - python3-pip=22.0.2+dfsg-1ubuntu0.4 -RUN pip install --upgrade jsonschema -COPY /scripts/networking/networking.py /networking.py -COPY /scripts/rpc/server.py server.py -COPY /scripts/rpc/swarm_server.py swarm_server.py -COPY /networks.json /networks.json - -ENTRYPOINT ["python3", "networking.py", "/networks.json"] \ No newline at end of file diff --git a/swarm/Dockerfile.swarm_node b/swarm/Dockerfile.swarm_node deleted file mode 100644 index 183ba9b..0000000 --- a/swarm/Dockerfile.swarm_node +++ /dev/null @@ -1,10 +0,0 @@ -FROM ubuntu:22.04 -RUN apt update \ - && apt install -y \ - python3=3.10.6-1~22.04 \ - python3-pip=22.0.2+dfsg-1ubuntu0.4 \ - && pip install jsonrpcserver==5.0.9 -COPY /scripts/rpc/server.py server.py -EXPOSE 65000 - -CMD ["python3", "server.py"] \ No newline at end of file diff --git a/swarm/Dockerfile.swarm_server b/swarm/Dockerfile.swarm_server deleted file mode 100644 index 0d35331..0000000 --- a/swarm/Dockerfile.swarm_server +++ /dev/null @@ -1,10 +0,0 @@ -FROM ubuntu:22.04 -RUN apt update \ - && apt install -y \ - python3=3.10.6-1~22.04 \ - python3-pip=22.0.2+dfsg-1ubuntu0.4 \ - && pip install jsonrpcserver==5.0.9 jsonrpcclient==4.0.3 requests==2.32.2 -COPY /scripts/rpc/swarm_server.py swarm_server.py -EXPOSE 65001 - -CMD ["python3", "swarm_server.py"] \ No newline at end of file From 39493f27e46e06a5bfaedc4c9a92a2544e2701b5 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Thu, 23 May 2024 04:00:33 +0500 Subject: [PATCH 68/72] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6572af5..0af8757 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# Итерация 4 +Из-за необходимости тестирования кода в лаборатории, а также сокращении итерации, проект не удалось закончить к дедлайну 22.05. Проект будет завершен в понедельник (27.05) или же в пятницу (24.05), если лаборатория будет открыта. # Итерация 3 Зависимости: Версия ОС: Ubuntu 22.04.4 LTS From 74d9fa6c20cd2d997d5edc65b4266708dea9b252 Mon Sep 17 00:00:00 2001 From: TokGrin <90797638+TokGrin@users.noreply.github.com> Date: Sun, 26 May 2024 14:47:27 +0300 Subject: [PATCH 69/72] edit servers to connect drones --- swarm/scripts/rpc/server.py | 24 +++++++++++++++++++--- swarm/scripts/rpc/swarm_server.py | 34 +++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/swarm/scripts/rpc/server.py b/swarm/scripts/rpc/server.py index d506f7f..504bef4 100644 --- a/swarm/scripts/rpc/server.py +++ b/swarm/scripts/rpc/server.py @@ -1,17 +1,35 @@ from jsonrpcserver import method, Success, Error, serve +from swarm.scripts.solutions.following.swarm_controlls import FollowMarkerWithCoords + +# Инициализация объекта дрона +drone_controller = FollowMarkerWithCoords() +drone_controller.main() @method(name="exec") -def exec(command: str) -> str: +def exec(json: dict) -> str: """ JSON-RPC method to execute a command. """ status = "OK" # Simulate command execution status # Print the command received - print(command) + print(json["command"]) + if json["command"] == "turn_starting_position": + drone_controller.turn_starting_position(json["coordinates"]) + if json["command"] == "land": + drone_controller.land() + if json["command"] == "set_swarm_is_coordinated": + drone_controller.set_swarm_is_coordinated() + if json["command"] == "save_coord_move_marker": + drone_controller.save_move_marker(json["coordinates"]) + drone_controller.save_coord_all_drones(json["coord_all_drones"]) + if json["command"] == "set_rotate": + drone_controller.set_rotate_flag() + if json["command"] == "reset_rotate": + drone_controller.reset_rotate_flag() # Return success or error response based on status - return Success(command) if status == "OK" else Error(1, command) + return Success(json["command"]) if status == "OK" else Error(1, json["command"]) if __name__ == "__main__": serve(port=65000) diff --git a/swarm/scripts/rpc/swarm_server.py b/swarm/scripts/rpc/swarm_server.py index 44af7f8..ba148ed 100644 --- a/swarm/scripts/rpc/swarm_server.py +++ b/swarm/scripts/rpc/swarm_server.py @@ -3,20 +3,42 @@ import requests SWARM = ["drone_1", "drone_2"] # List of drones in the swarm - +all_drones_coord = [] +move_marker_coord = [] @method(name="exec") -def exec(command: str) -> str: +def exec(json: dict) -> str: """ JSON-RPC method to execute a command on all drones in the swarm. """ + + params = { + "command": json["command"], + } + if json["command"] == "turn_starting_position": + params["coordinates"] = json["coordinates"] + all_drones_coord.append(json["coordinates"]) + if json["command"] == "save_coord_move_marker": + params["coordinates"] = json["coordinates"] + params["coord_all_drones"]= all_drones_coord + move_marker_coord.append(json["coordinates"]) + send_command_all_drones(params) + + if len(all_drones_coord) == len(SWARM): + params = { + "command": "set_swarm_is_coordinated" + } + send_command_all_drones(params) + + + # Return success response + return Success("OK") + +def send_command_all_drones(params): for node in SWARM: url = f"http://{node}:65000" - req = request("exec", command) + req = request("exec", params) response = requests.post(url, json=req) print(f"RESULT for '{url}' : {response}") - # Return success response - return Success("OK") - if __name__ == "__main__": serve(port=65001) From 2edfc4fc126664fc34296605865de1ea2338eceb Mon Sep 17 00:00:00 2001 From: elcstazi Date: Sun, 26 May 2024 14:52:28 +0300 Subject: [PATCH 70/72] drone control, server interaction --- .../solutions/following/swarm_controlls.py | 228 ++++++++++++++---- 1 file changed, 187 insertions(+), 41 deletions(-) diff --git a/swarm/scripts/solutions/following/swarm_controlls.py b/swarm/scripts/solutions/following/swarm_controlls.py index 65732bd..0b71985 100644 --- a/swarm/scripts/solutions/following/swarm_controlls.py +++ b/swarm/scripts/solutions/following/swarm_controlls.py @@ -12,6 +12,10 @@ from swarm.scripts.solutions.following.state import State from utils.write_text import write_status_on_image + +from jsonrpcclient import request +import requests + def dist_beetwen_points(p1, p2): return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) @@ -28,23 +32,50 @@ def __init__(self): self.num_of_rotates = 0 self.flag = 0 self.flag_two = 0 - # self.drone_id = None - # self.get_drone_id() self.drone_id = 1 self.coord_drone = None self.num_of_rotate = 0 + self.swarm_coordinated = False + self.coord_drone = None + + self.rotate_flag = 1 + self.move_flag = 0 + self.move_marker = 0 + def stop(self): self.is_stopped = True - # def get_drone_id(self): - # client = docker.client.from_env() - # self.drone_id = os.environ.get('HOSTNAME') - # if not self.drone_id: - # self.drone_id = -1 + def move_to_marker(self): + x, y, z =self.move_marker + x_un = self.coord_drone[0] - x + y_un = self.coord_drone[1] - y + z_un = self.coord_drone[2] - z + self.coord_drone = (x_un, y_un, z_un) + coord_drone = (x_un, y_un, z_un) + angle_degrees = 360 - self.num_of_rotates + + # Получаем матрицу поворота из вектора ориентации + angle_radians = math.radians(angle_degrees) + + # Преобразуем угол поворота в матрицу поворота + R = np.array([[np.cos(angle_radians), -np.sin(angle_radians), 0], + [np.sin(angle_radians), np.cos(angle_radians), 0], + [0, 0, 1]]) + + # Исходные координаты дрона + drone_coords = np.array(coord_drone) + + # Применяем поворот к координатам дрона + rotated_coords = np.dot(R, drone_coords) + # Добавляем координаты нулевой позиции дрона + x = int(rotated_coords[0] - 10) + y = int(rotated_coords[1]) + z = int(rotated_coords[2]) + return (State.MOVE, np.array([x, y, z], dtype=np.int32)) def find_marker(self, frame): corners, ids, rejected = cv2.aruco.detectMarkers(frame, ARUCO_DICT, parameters=ARUCO_PARAMS) @@ -60,18 +91,62 @@ def find_marker(self, frame): def make_action(self, m_corner): self.last_time = time.process_time() - rvecs , tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, camera_distortion) + rvecs, tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, + camera_distortion) state = self.get_state(tvecs[0][0]) if state == State.MOVE: - self.actions.put(state) + self.actions.put((state, None)) self.last_state = state - + def marker_coords(self, m_corner, marker_id): + self.last_time = time.process_time() + _, tvecs, _ = cv2.aruco.estimatePoseSingleMarkers(np.array([m_corner]), MARKER_LEN, camera_matrix, + camera_distortion) + tvec = tvecs[0][0] + marker_x, marker_y, marker_z = tvec[2], tvec[0], tvec[1] + x = z = y = 0 + drone_x = x + marker_x + drone_y = y + marker_y + drone_z = z + marker_z + print(drone_x, drone_y, drone_x) + angle_radians = math.radians(self.num_of_rotates) + + # Преобразуем угол поворота в матрицу поворота + R = np.array([[np.cos(angle_radians), -np.sin(angle_radians), 0], + [np.sin(angle_radians), np.cos(angle_radians), 0], + [0, 0, 1]]) + + # Исходные координаты дрона + drone_coords = np.array([drone_x, drone_y, drone_z]) + + # Применяем поворот к координатам дрона + rotated_coords = np.dot(R, drone_coords) + + # Добавляем координаты нулевой позиции дрона + drone_x_zero = int(rotated_coords[0]) + drone_y_zero = int(rotated_coords[1]) + drone_z_zero = int(rotated_coords[2]) + + # Добавляем смещение для учета положения дрона относительно маркера + if marker_id == MARKER_CENTER: + x = y = z = 0 # may be z = 50 + x = x + drone_x_zero + y = y + drone_y_zero + z = z + drone_z_zero + self.coord_drone = (x, y, z) + print(f"{self.drone_id}, {x}, {y}, {z}\n") + elif marker_id == MARKER_MOVE: + x = y = z = 0 # may be z = 50 + x = x + drone_x_zero + self.coord_drone[0] + y = y + drone_y_zero + self.coord_drone[1] + z = z + drone_z_zero + self.coord_drone[2] + self.move_marker = (x,y,z) + return (x, y, z) def process_frame(self, frame): ids = None is_find = True - if self.last_state == State.READY: + if self.last_state == State.READY and self.flag == int(self.swarm_coordinated): print("State.READY") ret = self.find_marker(frame) if ret is not None: @@ -82,58 +157,98 @@ def process_frame(self, frame): if marker_id == MARKER_CENTER and not self.flag: print("Send COORDS") self.marker_coords(marker_corner, MARKER_CENTER) - self.flag = 1 print("START LINE COORDS") print("degree rotate - ",self.num_of_rotates) - # i=1 - # for _ in range(self.num_of_rotates, 360, 45): - self.num_of_rotate = 360 - self.num_of_rotates - self.actions.put((State.ROTATE, None)) - # print(i) - # i+=1 - # self.num_of_rotates = 0 + # vvvvvvvvvvvv ОПРЕДЕЛИТЬ КОРРЕКТНЫЙ ИРЛ!!! vvvvvvvvvvvvvvvv + url = f"http://{""}:65001" + params = { + "command": "turn_starting_position", + "coordinates": self.coord_drone + } + req = request("exec", params) + response = requests.post(url, json=req) + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ print("END LINE COORDS") - - if self.flag == 1: + if self.flag == 1 and self.rotate_flag == 0: if marker_id == MARKER_MOVE: - self.marker_coords(marker_corner, MARKER_MOVE) + coord = self.marker_coords(marker_corner, MARKER_MOVE) + # print(мы нашили маркер мув и угол) + url = f"http://{""}:65001" + params = { + "command": "save_coord_move_marker", + "coordinates": coord + } + req = request("exec", params) + response = requests.post(url, json=req) + if self.flag == 1: + if self.move_flag == 1: state = self.move_to_marker() self.actions.put(state) self.last_state = state - + self.move_flag = 0 if marker_id == MARKER_STOP: print("Send END") - self.actions.put((State.END, None)) - self.last_state = State.END + # vvvvvvvvvvvv ОПРЕДЕЛИТЬ КОРРЕКТНЫЙ ИРЛ!!! vvvvvvvvvvvvvvvv + url = f"http://{""}:65001" + params = { + "command": "land" + } + req = request("exec", params) + response = requests.post(url, json=req) + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ if marker_id == MARKER_CENTER: + if self.rotate_flag == 1: + print("Send ROTATE 2") + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + self.rotate_flag = 0 + else: + url = f"http://{""}:65001" + params = { + "command": "set_rotate" + } + req = request("exec", params) + response = requests.post(url, json=req) + else: + if self.rotateflag == 1: print("Send ROTATE 2") self.actions.put((State.ROTATE, None)) self.last_state = State.ROTATE - else: - print("Send ROTATE 2") - self.actions.put((State.ROTATE, None)) - self.last_state = State.ROTATE + if self.flag == 1: + self.rotate_flag = 0 + else: - # if not self.flag: print("Send ROTATE 1") - self.actions.put((State.ROTATE, None)) - self.last_state = State.ROTATE + if self.rotate_flag == 0: + url = f"http://{""}:65001" + params = { + "command": "set_rotate" + } + req = request("exec", params) + response = requests.post(url, json=req) + if self.rotate_flag == 1: + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + if self.flag == 1: + self.rotate_flag = 0 if time.process_time() - self.last_time > TIMEOUT: print("Send END2") - self.actions.put((State.END, None)) - self.last_state = State.END - # time.sleep(1.5) + url = f"http://{""}:65001" + params = { + "command": "land", + } + req = request("exec", params) + response = requests.post(url, json=req) + write_status_on_image(frame, {"Battery": f"{self.last_battery_charge}%", "Last state": self.last_state}) self.video_writer.write(cv2.resize(frame, FRAME_SIZE)) return frame def drone_instructions(self, tello): tello.takeoff() - # tello.move_up(50) self.last_time = time.process_time() self.last_state = State.READY - # x = z = y = tello.get_current_xyz() while not self.is_stopped: try: @@ -142,7 +257,6 @@ def drone_instructions(self, tello): if state == State.END: break elif state == State.MOVE: - # print("DO MOVE") x, y, z = movements print(movements) tello.go_xyz_speed(int(x), int(y), int(z), SPEED) @@ -154,20 +268,52 @@ def drone_instructions(self, tello): tello.rotate_clockwise(x) self.num_of_rotates += x print("Rotate Degree", self.num_of_rotates) + + self.last_time -= 5 else: x = self.num_of_rotate tello.rotate_clockwise(x) self.num_of_rotate = 0 print("Rotate on first pose", self.num_of_rotate) self.num_of_rotates = 0 - - - except Empty: self.last_state = State.READY self.last_battery_charge = tello.get_battery() tello.land() + def turn_starting_position(self, coord): + if not self.flag and self.coord_drone == coord: + self.flag = 1 + self.num_of_rotate = 360 - self.num_of_rotates + self.actions.put((State.ROTATE, None)) + self.last_state = State.ROTATE + self.rotate_flag = 0 + return "OK" + + + def land(self): + self.actions.put((State.END, None)) + self.last_state = State.END + return "OK" + + def set_swarm_is_coordinated(self): + self.swarm_coordinated = True + return "OK" + + def set_rotate_flag(self): + self.rotate_flag = 1 + return "OK" + + def save_move_marker(self, coord): + self.move_flag = 1 + self.move_marker = coord + return "OK" + + def save_coord_all_drones(self, coord_all_drones): + self.coord_all_drones = coord_all_drones + return "OK" + + def main(self): self.is_stopped = False drone = Drone(self.drone_instructions, self.process_frame, show_stream=True) From cff8bfc6287d672a349917b394ce158a8da221e9 Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Tue, 28 May 2024 04:07:44 +0500 Subject: [PATCH 71/72] Update README.md --- README.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0af8757..16dacf0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,76 @@ # Итерация 4 -Из-за необходимости тестирования кода в лаборатории, а также сокращении итерации, проект не удалось закончить к дедлайну 22.05. Проект будет завершен в понедельник (27.05) или же в пятницу (24.05), если лаборатория будет открыта. +В результате итерации не удалось запустить рой. Исправлены недочеты прошлых итераций. +Зависимости: +Версия ОС: Ubuntu 22.04.4 LTS +Python 3.10.12 + +## Конфигурирование +Заполнить [конфигурационный файл](https://github.com/OSLL/tello-dev/blob/master/swarm/networks.json) +```json +{ + "ifaces" : { + "iface-name" : { + "ssid" : "", + "password" : "", + "ip": "172.18.0.3" + }, + "iface-name": { + "ssid" : "", + "password" : "", + "ip": "172.18.0.4" + } + } +} +``` +- Необходимо выполнить команду `ip a` и вставить имена необходимых wlan-интерфейсов вместо `iface-name`. +- Установить пакет `network-manager`: + `apt install network-manager=1.36.6-0ubuntu2` +- Выполнить команду `nmcli dev wifi list` и определить SSID wifi сетей причастных к дрону и вставить вместо `ssid` + +**Пример сконфигурированного файла** +```json +{ + "ifaces" : { + "wlo0" : { + "ssid" : "DRONE 1", + "password" : "", + "ip": "172.18.0.3" + }, + "wlo1": { + "ssid" : "DRONE 2", + "password" : "", + "ip": "172.18.0.4" + } + } +} +``` + +## Запуск +Установить зависимости +```bash +python3 -m pip install jsonrpcclient==4.0.3 requests==2.31.0 +``` +- Необходимо выполнить команду `docker compose -f ./swarm/docker-compose.yml up -d --build` (в одном месте монтируется с хоста папка и этого не избежать, иначе из контейнера нельзя будет управлять сетевыми устройствами) +- После запуска необходимо вызвать скрипт *client.py* передав флаги -c --ip , + где: + + --ip - P-адреса сервера JSON-RPC, к которому скрипт будет отправлять запросы, у нас это 127.0.0.1. + + -c - команда для дронов. + +Пример: +```bash +python3 ./swarm/scripts/rpc/client.py -c takeoff --ip 127.0.0.1 +``` +Результат: +```bash +RESULT for 'http://127.0.0.1:65001' : + {'jsonrpc': '2.0', 'result': 'OK', 'id': 1} +``` +## Презентация и видео +Презентация:[ОУПРПО. Итерация 4. Проект 12](https://docs.google.com/presentation/d/15QLL1ix36oWb84pD0Ya88piNtv9CHaV_Dnr0AQvBDYY/edit?usp=sharing) + + # Итерация 3 Зависимости: Версия ОС: Ubuntu 22.04.4 LTS From 8b1e1ac539e499b517a58f92e9298e56c34e7ddc Mon Sep 17 00:00:00 2001 From: Kocheshkov Alexander <88431323+KocheshkovAA@users.noreply.github.com> Date: Tue, 28 May 2024 14:39:19 +0500 Subject: [PATCH 72/72] Update README.md --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 16dacf0..765105c 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Python 3.10.12 ```bash python3 -m pip install jsonrpcclient==4.0.3 requests==2.31.0 ``` -- Необходимо выполнить команду `docker compose -f ./swarm/docker-compose.yml up -d --build` (в одном месте монтируется с хоста папка и этого не избежать, иначе из контейнера нельзя будет управлять сетевыми устройствами) +- Необходимо выполнить команду `docker compose --file ./swarm/docker-compose.yml up -d --build` (в одном месте монтируется с хоста папка и этого не избежать, иначе из контейнера нельзя будет управлять сетевыми устройствами) - После запуска необходимо вызвать скрипт *client.py* передав флаги -c --ip , где: @@ -67,7 +67,16 @@ python3 ./swarm/scripts/rpc/client.py -c takeoff --ip 127.0.0.1 RESULT for 'http://127.0.0.1:65001' : {'jsonrpc': '2.0', 'result': 'OK', 'id': 1} ``` -## Презентация и видео +## Остановка контейнеров +```bash +docker compose --file ./swarm/docker-compose.yml stop +``` +## Удаление контейнеров +```bash +docker compose --file ./swarm/docker-compose.yml down +``` + +## Презентация Презентация:[ОУПРПО. Итерация 4. Проект 12](https://docs.google.com/presentation/d/15QLL1ix36oWb84pD0Ya88piNtv9CHaV_Dnr0AQvBDYY/edit?usp=sharing)