From 176f636ba105d6bab25c7a49e6d80e180b4bfd27 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sat, 19 Jan 2019 20:28:14 +0300 Subject: [PATCH 01/27] Few minifixes --- Drone/{drone.csv => copter6349.csv} | 0 Drone/play_animation.py | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) rename Drone/{drone.csv => copter6349.csv} (100%) diff --git a/Drone/drone.csv b/Drone/copter6349.csv similarity index 100% rename from Drone/drone.csv rename to Drone/copter6349.csv diff --git a/Drone/play_animation.py b/Drone/play_animation.py index cc4686e..6289e8b 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -8,9 +8,9 @@ animation_file_path = 'drone.csv' frames = [] -def takeoff(): +def takeoff(h=1.75): LedLib.wipe_to(0, 255, 0) - FlightLib.takeoff(1.75) + FlightLib.takeoff(h) def land(): @@ -29,8 +29,8 @@ def do_next_animation(current_frame): ) -def read_animation_file(): - with open(animation_file_path) as animation_file: +def read_animation_file(filepath=animation_file_path): + with open(filepath) as animation_file: csv_reader = csv.reader( animation_file, delimiter=',', quotechar='|' ) From 90ed17285a43ec464370f8cf70404e7a994769be Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sat, 19 Jan 2019 20:33:57 +0300 Subject: [PATCH 02/27] Completely new client and server --- Drone/Client.py | 272 +++++++++----- Drone/client_config.ini | 17 + Server/Server.py | 635 ++++++++++++++------------------- Server/back_1_rc.py | 73 ---- Server/gui/back.png | Bin 4391 -> 0 bytes Server/gui/back_1.qrc | 5 - Server/gui/gui.ui | 477 ------------------------- Server/gui/telem.qrc | 5 - Server/gui/telem_bakground.png | Bin 1027 -> 0 bytes Server/gui/telemetry.ui | 536 ---------------------------- Server/gui_telem.py | 214 ----------- Server/main_gui.py | 203 ----------- Server/server_config.ini | 11 + Server/telem_rc.py | 72 ---- 14 files changed, 486 insertions(+), 2034 deletions(-) create mode 100644 Drone/client_config.ini delete mode 100644 Server/back_1_rc.py delete mode 100755 Server/gui/back.png delete mode 100755 Server/gui/back_1.qrc delete mode 100755 Server/gui/gui.ui delete mode 100755 Server/gui/telem.qrc delete mode 100755 Server/gui/telem_bakground.png delete mode 100755 Server/gui/telemetry.ui delete mode 100644 Server/gui_telem.py delete mode 100644 Server/main_gui.py create mode 100644 Server/server_config.ini delete mode 100644 Server/telem_rc.py diff --git a/Drone/Client.py b/Drone/Client.py index 71e403f..8b1a7b5 100755 --- a/Drone/Client.py +++ b/Drone/Client.py @@ -1,99 +1,207 @@ +from __future__ import print_function +import sys import socket -import play_animation +import struct +import random import time -import ntplib -from threading import Thread -sock = socket.socket() -serv = '192.168.1.10' # Change to server ip -port = 35001 -sock.connect((serv, port)) -sock.send(bytes('left', 'utf-8')) -command = '' +import threading +import ConfigParser +from contextlib import closing + +#import rospy + +#import play_animation + +random.seed() + +NTP_PACKET_FORMAT = "!12I" +NTP_DELTA = 2208988800L # 1970-01-01 00:00:00 +NTP_QUERY = '\x1b' + 47 * '\0' -def receive(): - global command - try: +def get_ntp_time(host, port): + with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s: + s.sendto(NTP_QUERY, (host, port)) + msg, address = s.recvfrom(1024) + unpacked = struct.unpack(NTP_PACKET_FORMAT, msg[0:struct.calcsize(NTP_PACKET_FORMAT)]) + return unpacked[10] + float(unpacked[11]) / 2**32 - NTP_DELTA + + +def reconnect(t=1): + print("Trying to connect to", host, ":", port, "...") + connected = False + global clientSocket + while not connected: + try: + clientSocket = socket.socket() + clientSocket.connect((host, port)) + connected = True + print("Connection successful") + except socket.error as e: + print("Waiting for connection:", e) + time.sleep(t) + + +def send_all(msg): + clientSocket.sendall(struct.pack('>I', len(msg)) + msg) + + +def recive_all(n): + data = b'' + while len(data) < n: + packet = clientSocket.recv(min(n - len(data), BUFFER_SIZE)) + if not packet: + return None + data += packet + return data + + +def recive_message(): + raw_msglen = recive_all(4) + if not raw_msglen: + return None + msglen = struct.unpack('>I', raw_msglen)[0] + msg = recive_all(msglen) + return msg + + +def form_command(command, args=()): + return " ".join([command, args]) + + +def parse_command(command_input): + args = command_input.split() + command = args.pop(0) + return command, args + + +def recive_file(filename): + print("Reciving file:", filename) + with open(filename, 'wb') as file: # TODO add directory while True: - data = str(sock.recv(1024)) - try: - if b'programm' in data: - anim = open('anim.csv', 'w') - data = data[data.index(b'programm') + 8:] - anim.write(data) - - while True: - data = str(sock.recv(1024)) - - if b'stop' in data: - anim.write(data[:data.index(b'stop')]) - break - else: - anim.write(data) - - else: - try: - sq = data.split('$$') - for i in range(len(sq) - 1): - print(sq[i]) - command = sq[i] - - except Exception as e: - print(e) - - except: - print('er') - sock.close() - except KeyboardInterrupt: - print("Shutting down") - - led.off() - sock.close() + data = recive_message() #clientSocket.recv(BUFFER_SIZE) + if data: + print(data) + if parse_command(data.decode("UTF-8"))[0] == "/endoffile": + print("File recived") + break + file.write(data) -def time_synch(): - c = ntplib.NTPClient() - response = c.request('ntp1.stratum2.ru') - return response.tx_time-time.time() +def write_to_config(section, option, value): + config.set(section, option, value) + with open(CONFIG_PATH, 'w') as file: + config.write(file) -def pl_anim(): - global command - play_animation.read_animation_file() - dtime = time_synch() - time.time() - ok = 0 - t_st=0 - while True: - - if 'begin_anim' in command: - t_st = int(command[command.index('('):]) - - if t_st == dtime+time.time: +def animation_player(running_event, stop_event): + print("Animation thread activated") + rate = rospy.Rate(1000 / 100) + play_animation.takeoff(TAKEOFF_HEIGHT) + for current_frame in play_animation.frame(): + running_event.wait() + if stop_event.is_set(): break - if 'synch' in command: - dtime=time_synch() - time.time() - print(dtime) - play_animation.takeoff() - for frame in play_animation.frame(): - if command != 'pause': - time.sleep(0.1) - play_animation.do_next_animation(frame) + play_animation.do_next_animation(current_frame) + rate.sleep() + else: + play_animation.land() + print("Animation ended") + print("Animation thread closed") -if __name__ == "__main__": - t_0 = Thread(target=receive) - t_0.daemon = True - t_0.start() - - t_1 = Thread(target=pl_anim) - t_1.daemon = True - t_1.start() - - - - +stop_animation_event = threading.Event() +running_animation_event = threading.Event() +animation_thread = threading.Thread(target=animation_player, args=(running_animation_event, stop_animation_event)) +def start_animation(): + play_animation.read_animation_file(animation_file) + print("Starting animation!") + resume_animation() + animation_thread.start() +def resume_animation(): + print("Resuming animation") + running_animation_event.set() + + +def pause_animation(): + print("Pausing animation") + running_animation_event.clear() + + +def stop_animation(): + stop_animation_event.set() + running_animation_event.clear() + print("Stopping animation") + animation_thread.join() + + +CONFIG_PATH = "client_config.ini" +config = ConfigParser.ConfigParser() +config.read(CONFIG_PATH) + + +port = int(config.get('SERVER', 'port')) +host = config.get('SERVER', 'host') +BUFFER_SIZE = int(config.get('SERVER', 'buffer_size')) +NTP_HOST = config.get('NTP', 'host') +NTP_PORT = int(config.get('NTP', 'port')) + +files_directory = config.get('FILETRANSFER', 'files_directory') +animation_file = config.get('COPTER', 'animation_file') + +COPTER_ID = config.get('COPTER', 'id') +if COPTER_ID == 'default': + COPTER_ID = 'copter' + str(random.randrange(9999)).zfill(4) + write_to_config('COPTER', 'id', COPTER_ID) + +TAKEOFF_HEIGHT = float(config.get('COPTER', 'takeoff_height')) + +print("Client started on copter:", COPTER_ID) +print("NTP time:", time.ctime(get_ntp_time(NTP_HOST, NTP_PORT))) +print("System time", time.ctime(time.time())) + +reconnect() + +print("Connected to server") + +try: + while True: + try: + message = recive_message() + if message: + message = message.decode("UTF-8") + command, args = parse_command(message) + print("Command from server:", command, args) + if command == "writefile": + recive_file(args[0]) + elif command == "starttime": + starttime = float(args[0]) + print("Starting on:", time.ctime(starttime)) + dt = starttime - get_ntp_time(NTP_HOST, NTP_PORT) + print("Until start:", dt) + rospy.Timer(rospy.Duration(dt), start_animation, oneshot=True) + elif command == 'request': + request_target = args[0] + print("Got request for:", request_target) + response = "" + if request_target == 'someshit': + response = "dont_have_any" + elif request_target == 'id': + response = COPTER_ID + send_all(bytes(form_command("response", response))) + print("Request responded with:", response) + + except socket.error: + print("Connection lost... reconnecting") + reconnect() + print("Re-connection successful") +except KeyboardInterrupt: + print("Shutdown on keyboard interrupt") +finally: + clientSocket.close() + diff --git a/Drone/client_config.ini b/Drone/client_config.ini new file mode 100644 index 0000000..71439a9 --- /dev/null +++ b/Drone/client_config.ini @@ -0,0 +1,17 @@ +[SERVER] +port = 25000 +host = 192.168.43.168 +buffer_size = 1024 + +[FILETRANSFER] +files_directory = files + +[NTP] +host = ntp1.stratum2.ru +port = 123 + +[COPTER] +id = copter6349 +takeoff_height = 1.75 +takeoff_timeout = 7 +animation_file = animation.csv diff --git a/Server/Server.py b/Server/Server.py index db7ed54..e23082f 100644 --- a/Server/Server.py +++ b/Server/Server.py @@ -1,388 +1,289 @@ -# -*- coding: utf-8 -*- . -"""Code by Alexandr Osherov 10 class, phone - +79251834732, email - allexandr2001@mail.ru """ -from PyQt5.QtWidgets import * -from PyQt5.QtGui import * -from PyQt5.QtCore import * -from mpl_toolkits.mplot3d import Axes3D -import matplotlib.pyplot as plt -import time -import socket +from tkinter import * +from tkinter import ttk +from tkinter import filedialog +import ttkwidgets + import os -import easygui +import sys +import glob +import time +import struct +import socket import threading -from threading import Thread -import math -import requests -import json -import main_gui -import gui_telem -import ntplib -ip = [1, 2] -sq_rad = 0 -sq_cet = 0 -cr_rad = 0 -cr_cet = 0 -copters = 1 -conn = [] -conn_2 = [] -afile = '' -data = b'' -addr = [] -addr_2 = [] -coord = [] -d_time = 0 -size_scene=[2,2,2] -sock = socket.socket() +import collections +import configparser -sock.bind(('', 35001)) # назначается адресс и порт связи для отпраки команд на коптеры -sock.listen(1) - -sock_2 = socket.socket() -sock_2.bind(('', 35002)) # назначается адресс и порт связи для приема данных с коптеров -sock_2.listen(1) +# All imports sorted in pyramid -class Dialog(QMainWindow, gui_telem.Ui_Dialog): - def __init__(self): - super().__init__() - self.setupUi(self) +def auto_connect(): + while True: + ServerSocket.listen(1) + c, addr = ServerSocket.accept() + print("Got connection from:", str(addr)) + #client_thread = threading.Thread(target=on_new_client, args=(c, addr)) + #client_thread.start() - def up(self): - self.voltage_2.setText('1234567') + if not any(client_addr == addr[0] for client_addr in Client.clients.keys()): + client = Client(addr[0]) + print("New client") + else: + print("Reconnected client") + Client.clients[addr[0]].connect(c, addr) -class Widget(QMainWindow, main_gui.Ui_MainWindow): - def __init__(self): - super().__init__() - self.setupUi(self) - self.start_animation_button.clicked.connect(self.start_animation) - self.stop_swarm_but.clicked.connect(self.stop_swarm) - self.show_3d_scene_button.clicked.connect(self.show_3d) - self.disarm_all_button.clicked.connect(self.disarm) - self.turn_off_led_button.clicked.connect(self.off_leds) - self.turn_on_led_button.clicked.connect(self.on_leds) - self.upload_animation_button.clicked.connect(self.upload_animation) - self.land_all_button.clicked.connect(self.land) - self.take_off_button.clicked.connect(self.take_off) - #self.number_animation_copters.clicked.connect(self.number_animation) synch_button - self.synch_button.clicked.connect(self.synch) - self.take_off_n_button.clicked.connect(self.take_off_n) - self.land_n_button.clicked.connect(self.land_n) - self.disarm_n_button.clicked.connect(self.disarm_n) - self.land_spinBox.valueChanged.connect(self.land_led) - self.disarm_spinBox.valueChanged.connect(self.disarm_led) - self.take_off_spinBox.valueChanged.connect(self.take_off_led) - self.safty_button.clicked.connect(self.safty) - self.connect_button.clicked.connect(self.connect) - self.swarm_size_spinBox.valueChanged.connect(self.number_copters) +NTP_DELTA = 2208988800 # 1970-01-01 00:00:00 +NTP_QUERY = b'\x1b' + bytes(47) - - def receiver(self): - global copters - global addr - while True: +def get_ntp_time(ntp_host, ntp_port): + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: + s.sendto(NTP_QUERY, (ntp_host, ntp_port)) + msg, _ = s.recvfrom(1024) + return int.from_bytes(msg[-8:], 'big') / 2 ** 32 - NTP_DELTA + + +def requires_connect(f): + def wrapper(*args, **kwargs): + if args[0].connected: + return f(*args, **kwargs) + else: + print("Function requires client to be connected!") + return wrapper + + +class Client: + clients = {} + + def __init__(self, ip): + self.socket = None + self.addr = None + + self._send_queue = collections.deque() + self._received_queue = collections.deque() + self._request_queue = collections.OrderedDict() + + self.copter_id = None + self.malfunction = False + + Client.clients[ip] = self + + self.connected = False + + def connect(self, client_socket, client_addr): + print("Client connected") + self._send_queue = collections.deque() # comment for resuming queue after reconnection + + self.socket = client_socket + self.addr = client_addr + + self.socket.setblocking(0) + self.connected = True + client_thread = threading.Thread(target=self._run, args=()) + client_thread.start() + if self.copter_id is None: + self.copter_id = self.get_response("id") + print("Got copter id:", self.copter_id) + drone_list.insert("", "end", self.addr[0], text=self.copter_id) + + def _send_all(self, msg): + self.socket.sendall(struct.pack('>I', len(msg)) + msg) + + def _receive_all(self, n): + data = b'' + while len(data) < n: + packet = self.socket.recv(min(n - len(data), BUFFER_SIZE)) + if not packet: + return None + data += packet + return data + + def _receive_message(self): + raw_msglen = self._receive_all(4) + if not raw_msglen: + return None + msglen = struct.unpack('>I', raw_msglen)[0] + msg = self._receive_all(msglen) + return msg + + def _run(self): + while self.connected: try: - for k in range(copters): - a = requests.get('http://' + addr[k][0] + ':8081/aruco_map') - tem = json.loads(a.text) - - coord[k] = str(tem['x']) + ',' + str(tem['y']) + ',' + str(tem['z']) + ',' + \ - str(tem['mode']) + ',' + str(tem['armed']) + ',' + str(tem['frame_id']) + str( - tem['voltage']) + ',' + \ - str(tem['yaw']) + ',' + str(tem['pitch']) + ',' + str(tem['roll']) + ',' + \ - str(tem['vx']) + ',' + str(tem['vy']) + ',' + str(tem['vz']) - - #time.sleep(0.05) - - - except Exception as e: - pass - - def sender(self, com, num): - global conn - global conn_2 - global copters - print(com) - print(num) - try: - if num == 'all': - for i in range(copters): - conn[i].send(com + b'$$') - print(com + b'$$') - elif int(num) > 0: - conn[int(num) - 1].send(com + b'$$') - except: - pass - - def message(self, mes): - pass - - def connect(self): - global copters - global conn - global conn_2 - global addr - global addr_2 - global coord - - addr_2 = [] - - conn = [] - conn_2 = [] - - self.message('Try connect') - for i in range(copters): - conn.append(0) - addr.append(0) - coord.append('0') - - t_0 = Thread(target=self.connect_init) - t_0.daemon = True - t_0.start() - - def connect_init(self): - self.state_label.setText("

Wait

") - global copters - - global conn - global addr - global conn_2 - global addr_2 - - for i in range(copters): - conn[i], addr[i] = sock.accept() - print("connected_controllers:", addr[i]) - - self.disarm_spinBox.setMaximum(copters) - self.land_spinBox.setMaximum(copters) - self.take_off_spinBox.setMaximum(copters) - self.state_label.setText("

Connect

") - - t = Thread(target=self.receiver) - t.daemon = True - t.start() - - def safty(self): - self.message('safty check') - self.sender(b'f.safety_check(False)', 'all') - - def take_off(self): - self.message('take off') - self.sender(b'f.takeoff(z=2, speed=2,speed_takeoff=2 , timeout=2)', 'all') - - def take_off_n(self): - self.message('take off n') - self.sender(b'f.takeoff()', str(self.take_off_spinBox.value())) - - def land(self): - self.message('land') - self.sender(b'f.land(preland=False)', 'all') - - def land_n(self): - self.message('land n') - self.sender(b'f.land(preland=False)', str(self.land_spinBox.value())) - - def disarm(self): - self.sender(b'f.arming(False)', 'all') - - def disarm_n(self): - self.sender(b'f.arming(False)', str(self.disarm_spinBox.value())) - - def off_leds(self): - self.sender(b'led.off()', 'all') - - def land_led(self): - self.sender(b'led.off()', 'all') - self.sender(b'led.fill(255,0,0)', self.land_spinBox.value()) - # print(1) - - def disarm_led(self): - self.sender(b'led.off()', 'all') - self.sender(b'led.fill(0,255,0)', self.disarm_spinBox.value()) - - def take_off_led(self): - self.sender(b'led.off()', 'all') - self.sender(b'led.fill(0,0,255)', self.take_off_spinBox.value()) - - def on_leds(self): - self.sender(b'led.fill(0,0,255)', 'all') - - def number_copters(self): - global copters - copters = self.swarm_size_spinBox.value() - - def upload_animation(self): - global afile - afile = easygui.fileopenbox(filetypes=["*.csv"],multiple=True) # вызов окна проводника для выбора файла - - def start_animation(self): - global afile - global d_time - for counter, sub_file in enumerate(afile): - f = open(sub_file, 'r') - prog = f.read() - self.sender(b'programm' + bytes(prog, 'utf-8')+b'stop', str(counter)) - time.sleep(0.1) - for i in range(len(afile)): - self.sender(bytes('begin_anim('+str(time.time()+d_time+10)+')','utf-8', str(counter))) - - t1 = Thread(target=self.start_retime) - t1.daemon = True - t1.start() - - - def start_retime(self): - for i in range(11): - time.sleep(1) - self.time_to_start_label.setText("

"+str(10-i)+"

") - '''if i==10: - k=0 - while True: - k+=1 - time.sleep(0.2r) - self.time_to_start_label.setText("

"+k*'.'+"

") - if k>3: - k=0'''# for ... animation - self.time_to_start_label.setText("

Take off

") - time.sleep(2) - self.time_to_start_label.setText("

") - - - - def stop_swarm(self): - pass - - def synch(self): - global d_time - self.sender(b'synch', 'all') - c = ntplib.NTPClient() - response = c.request('ntp1.stratum2.ru') - d_time = response.tx_time-time.time() - print(d_time) - - def show_3d(self): - global size_scene - global data - global copters - global coord - fig = plt.figure() - ax = fig.add_subplot(111, projection='3d') - updateDialog = Dialog() - updateDialog.show() - - while True: - s = str(self.console_textEdit.toPlainText()) - #print(s) - if '>' in s: - - print(s[:-2], s[s.index('>') - 1]) - self.console_textEdit.setText('') - if s[s.index('>') - 1] == '0': - self.sender(bytes(str(s[:s.index('>') - 1]), 'utf-8'), 'all') - #print(s[:s.index('>') - 1], 'all') + if self._send_queue: + msg = self._send_queue.popleft() + print("Send", msg, "to", self.addr) + self._send_all(msg) else: - self.sender(bytes(str(s[:s.index('>') - 1]), 'utf-8'), str(s[s.index('>') - 1])) - #print('sender', s[s.index('>') - 1]) - try: + msg = "ping" + #self._send_all(msg) - i = updateDialog.number_spinBox.value() - if i > 0: - i -= 1 - - coord_drone = [] - coord_drone = coord[i].split(',') - - updateDialog.z_2.setText("

" + coord_drone[ - 0] + "

") - updateDialog.x_2.setText("

" + coord_drone[ - 1] + "

") - updateDialog.y_2.setText("

" + coord_drone[ - 2] + "

") - updateDialog.mode_2.setText("

" + coord_drone[ - 3] + "

") - updateDialog.armed_2.setText("

" + coord_drone[ - 4] + "

") - updateDialog.frame_id_2.setText("

" + coord_drone[ - 5] + "

") - updateDialog.voltage_2.setText("

" + coord_drone[ - 6] + "

") - updateDialog.yaw2.setText("

" + coord_drone[ - 7] + "

") - updateDialog.pitch_2.setText("

" + coord_drone[ - 8] + "

") - updateDialog.roll_2.setText("

" + coord_drone[ - 9] + "

") - updateDialog.vx_2.setText("

" + coord_drone[ - 10] + "

") - updateDialog.vy_2.setText("

" + coord_drone[ - 11] + "

") - updateDialog.vz_2.setText("

" + coord_drone[ - 12] + "

") - except Exception as e: - # print(e) - pass - try: - - n = 0 - # set size of scene - - ax.set_xlim(0, size_scene[0]) - ax.set_ylim(0, size_scene[1]) - ax.set_zlim(0, size_scene[2]) - - ax.set_xlabel('x') - ax.set_ylabel('y') - ax.set_zlabel('z') - - plt.pause(0.01) - - ax.clear() - try: - for i in coord: - co = (0, 0, 0) - n += 1 - - if self.land_spinBox.value() == n: - co = (1, 0, 0) - if self.take_off_spinBox.value() == n: - co = (1, 0, 0) - if self.disarm_spinBox.value() == n: - co = (1, 0, 0) - - ax.scatter(float(i.split(',')[0]), float(i.split(',')[1]), float(i.split(',')[2]), s=50, c=co, - marker='.') - ax.text(float(i.split(',')[0]), float(i.split(',')[1]), float(i.split(',')[2]), str(n), size=10, - zorder=1, color=(0, 0, 0)) - - except Exception as e: - #print(e) + try: # check if data in buffer + check = self.socket.recv(BUFFER_SIZE, socket.MSG_PEEK) + if check: + received = self._receive_message() + if received: + received = received.decode("UTF-8") + print("Recived", received, "from", self.addr) + command, args = Client.parse_command(received) + if command == "response": + for key, value in self._request_queue.items(): + if not value: + self._request_queue[key] = args[0] + print("Request successfully closed") + break + else: + self._received_queue.appendleft(received) + except socket.error: pass - ax.set_xlim(0, size_scene[0]) - ax.set_ylim(0, size_scene[1]) - ax.set_zlim(0, size_scene[2]) - - - ax.set_xlabel('x') - ax.set_ylabel('y') - ax.set_zlabel('z') - - plt.draw() - except KeyboardInterrupt: - print('stop') + except socket.error as e: + print("Client error, disconnected", e) + self.connected = False + self.socket.close() break + # time.sleep(0.05) - plt.show() + @staticmethod + def form_command(command: str, args=()): # Change for different protocol + return " ".join([command, *args]) + + @staticmethod + def parse_command(command_input): + args = command_input.split() + command = args.pop(0) + return command, args + + @requires_connect + def send(self, *messages): + for message in messages: + self._send_queue.append(bytes(message, "UTF-8")) + + @staticmethod + def broadcast(message, force_all=False): + for client in Client.clients.values(): + if (not client.malfunction) or force_all: + client.send(message) + + @requires_connect + def send_file(self, filepath, dest_filename): + print("Sending file ", dest_filename) + self.send(Client.form_command("writefile", (dest_filename,))) + file = open(filepath, 'rb') + chunk = file.read(BUFFER_SIZE) + while chunk: + self._send_queue.append(chunk) + chunk = file.read(BUFFER_SIZE) + file.close() + self.send(Client.form_command("/endoffile")) + print("File sent") + + @requires_connect + def get_response(self, requested_value): + self._request_queue[requested_value] = "" + self.send(Client.form_command("request", (requested_value, ))) + + while not self._request_queue[requested_value]: + pass + + return self._request_queue.pop(requested_value) - -app = QApplication([]) -w = Widget() -w.show() - -app.exec() +# UI functions +def stop_swarm(): + Client.broadcast("stop") # для тестирования +def send_animations(): + path = filedialog.askdirectory(title="Animation directory") + if path: + print("Selected directory:", path) + files = [file for file in glob.glob(path+'/*.csv')] + names = [os.path.basename(file).split(".")[0] for file in files] + print(files) + for file, name in zip(files, names): + for copter in Client.clients.values(): + if name == copter.copter_id: + copter.send_file(file, "animation.csv") # TODO config + else: + print("Filename not matches with any drone connected") + #dr = next(iter(Client.clients.values())) # костыль для тестирования + #ANS = dr.get_response("someshit") + #print(ANS) + + +def send_starttime(dt=60): + timenow = time.time() + print('Now:', time.ctime(timenow), "+ dt =", dt) + Client.broadcast(Client.form_command("starttime", (str(timenow+dt), ))) + + +# UI build here +root = Tk() +root.wm_title("Drone swarm operation server") +root.style = ttk.Style() +root.style.theme_use("vista") + +leftFrame = Frame(root) +leftFrame.grid(row=0, column=0, padx=10, pady=10) +rightFrame = Frame(root) +rightFrame.grid(row=0, column=1, padx=10, pady=10) + +drone_list = ttkwidgets.CheckboxTreeview(leftFrame, columns=("addr", "connected")) +#drone_list["columns"] = ("addr") +#drone_list.column("name") #width=100 +#drone_list.column("addr") +drone_list.heading("#0", text="Drone name") +drone_list.heading("#1", text="Connection adress") +drone_list.heading("#2", text="Connection status") +drone_list.pack() + +button_frame = Frame(leftFrame, borderwidth=1, relief="solid") +button_frame.pack(fill=BOTH, expand=True) + +stop_all_btn = ttk.Button(button_frame, text="Stop swarm", command=stop_swarm) +stop_all_btn.pack(side=RIGHT, padx=5, pady=5) + +send_animation_btn = ttk.Button(button_frame, text="Send animations", command=send_animations) +send_animation_btn.pack(side=RIGHT, padx=5, pady=5) + +send_starttime_btn = ttk.Button(button_frame, text="Start animation after...", command=send_starttime) +send_starttime_btn.pack(side=RIGHT, padx=5, pady=5) + + +def gui_update(): + time.sleep(0.1) + + +# reading config +config = configparser.ConfigParser() +config.read("server_config.ini") + +port = int(config['SERVER']['port']) +BUFFER_SIZE = int(config['SERVER']['buffer_size']) +NTP_HOST = config['NTP']['host'] +NTP_PORT = int(config['NTP']['port']) + + +ServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socket.socket() # +ServerSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +host = socket.gethostname() +ip = socket.gethostbyname_ex(host)[-1] + +print('Server started on', host, ip, ":", port) +#print('Now:', time.ctime(get_ntp_time(NTP_HOST, NTP_PORT))) +print('Waiting for clients...') +ServerSocket.bind((ip[-1], port)) + +autoconnect_thread = threading.Thread(target=auto_connect) +autoconnect_thread.daemon = True +autoconnect_thread.start() + + +if __name__ == '__main__': + try: + mainloop() + except KeyboardInterrupt: + print("Stopping server by keyboard interrupt") + finally: + ServerSocket.close() + print("Server shutdown") diff --git a/Server/back_1_rc.py b/Server/back_1_rc.py deleted file mode 100644 index e23970e..0000000 --- a/Server/back_1_rc.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- - -# Resource object code -# -# Created by: The Resource Compiler for PyQt5 (Qt v5.11.2) -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore - -qt_resource_data = b"\ -\x00\x00\x01\x01\ -\x00\ -\x00\x11\x27\x78\x9c\xeb\x0c\xf0\x73\xe7\xe5\x92\xe2\x62\x60\x60\ -\xe0\xf5\xf4\x70\x09\x62\x60\x60\x05\x32\x99\x2e\x70\x30\x01\x29\ -\x07\x79\x2f\x46\x20\xc5\x58\x1c\xe4\xee\xc4\xb0\xee\x9c\xcc\x4b\ -\x20\x87\x25\xdd\xd1\xd7\x91\x81\x61\x63\x3f\xf7\x9f\x44\x90\x52\ -\xce\x02\x8f\xc8\x62\x06\x06\xbe\xc3\x20\xcc\x78\x3c\x7f\x45\x0a\ -\x03\x83\xc0\x1e\x4f\x17\xc7\x90\x8a\xb8\xb7\xd7\x37\x0a\x1e\x32\ -\x60\x60\x71\x74\xe4\xcf\x73\xef\xf4\x2a\x4f\x2c\x5a\xd4\xc2\xa4\ -\xf0\xa0\x6c\xf2\x7c\xfd\x87\x71\xdf\x6b\xf9\x19\x7e\x74\xee\xfd\ -\x3e\xe7\xf3\x1c\xff\xec\xb5\xaf\x77\x9d\x63\x64\xf8\xd1\xf4\x3d\ -\x12\x68\xe4\x8f\x6c\x26\x09\x06\x86\x06\x16\x46\x1e\xa0\x13\x9a\ -\x18\xd8\x18\x18\x14\x1c\x19\x98\x19\x18\x26\x28\x34\x00\x9d\xe3\ -\x21\x70\x00\xa8\x46\x85\x23\x01\x48\x0a\xb1\x18\x80\x9c\x30\xaa\ -\x7c\x54\xf9\xa8\xf2\x51\xe5\xa3\xca\x47\x95\x8f\x2a\x1f\x55\x3e\ -\xaa\x7c\x54\xf9\xa8\xf2\x51\xe5\xa3\xca\x47\x95\x8f\x2a\x1f\x55\ -\x4e\xbc\x72\x96\x9e\x8f\x0c\x2f\xa5\x79\x56\x38\x34\x3f\xa9\x06\ -\x72\x19\x3c\x5d\xfd\x5c\xd6\x39\x25\x34\x01\x00\xe9\xcb\xf7\x1d\ -\ -" - -qt_resource_name = b"\ -\x00\x04\ -\x00\x06\x87\x9b\ -\x00\x62\ -\x00\x61\x00\x63\x00\x6b\ -\x00\x08\ -\x07\x9e\x5a\x47\ -\x00\x62\ -\x00\x61\x00\x63\x00\x6b\x00\x2e\x00\x70\x00\x6e\x00\x67\ -" - -qt_resource_struct_v1 = b"\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x0e\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\ -" - -qt_resource_struct_v2 = b"\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x0e\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x64\x8d\x7d\xe9\xe9\ -" - -qt_version = [int(v) for v in QtCore.qVersion().split('.')] -if qt_version < [5, 8, 0]: - rcc_version = 1 - qt_resource_struct = qt_resource_struct_v1 -else: - rcc_version = 2 - qt_resource_struct = qt_resource_struct_v2 - -def qInitResources(): - QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) - -def qCleanupResources(): - QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) - -qInitResources() diff --git a/Server/gui/back.png b/Server/gui/back.png deleted file mode 100755 index 0a306ec6a32325a582d39a595eb8206b64f2ce43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4391 zcmeAS@N?(olHy`uVBq!ia0y~yUC!*C^P__;~{VWs78e&0Z0n57ywDmQRSl{GnxoSv&U#jFj_{ARtKXM z<(@#6$6Js%lfO7pC6Xns-+Y(+45y85}Sb4q9e E0O`y39RL6T diff --git a/Server/gui/back_1.qrc b/Server/gui/back_1.qrc deleted file mode 100755 index cbabc36..0000000 --- a/Server/gui/back_1.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - back.png - - diff --git a/Server/gui/gui.ui b/Server/gui/gui.ui deleted file mode 100755 index 1d1ea3d..0000000 --- a/Server/gui/gui.ui +++ /dev/null @@ -1,477 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 1280 - 720 - - - - - 1280 - 720 - - - - - 1280 - 720 - - - - Drone Swarm - - - - - - 760 - 70 - 100 - 40 - - - - Take off all - - - - - - 890 - 70 - 91 - 40 - - - - Land all - - - - - - 1010 - 70 - 101 - 40 - - - - background-color: red - - - - Disarm all - - - - - - 760 - 150 - 100 - 40 - - - - Take off n - - - - - - 890 - 150 - 91 - 40 - - - - - - - Land n - - - - - - 1010 - 150 - 101 - 40 - - - - background-color: red - - - - Disarm n - - - - - - 790 - 120 - 50 - 22 - - - - - - - 910 - 120 - 50 - 22 - - - - - - - 1040 - 120 - 50 - 22 - - - - - - - 840 - 20 - 200 - 20 - - - - <html><head/><body><p><span style=" font-size:12pt; color:#c8c8c8;">Control console</span></p></body></html> - - - Qt::AlignCenter - - - - - - 1140 - 60 - 100 - 61 - - - - - - - Turn on Leds - - - - - - 1140 - 140 - 100 - 61 - - - - Turn off Leds - - - - - - 220 - 510 - 141 - 51 - - - - - - - Stop swarm - - - - - - 620 - 60 - 111 - 40 - - - - - - - Connect - - - - - - 260 - 80 - 50 - 20 - - - - - - - 240 - 50 - 100 - 20 - - - - <html><head/><body><p><span style=" font-size:9pt;">Swarm Size</span></p></body></html> - - - Qt::AlignCenter - - - - - - 840 - 260 - 200 - 20 - - - - <html><head/><body><p><span style=" font-size:12pt; color:#c8c8c8;">Send command</span></p></body></html> - - - Qt::AlignCenter - - - - - - 640 - 290 - 591 - 271 - - - - background-color: rgb(1, 36, 86) - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; color:#ffffff;">...</span></p></body></html> - - - - - - 220 - 300 - 141 - 51 - - - - - - - Show 3d scene - - - - - - 220 - 370 - 141 - 51 - - - - - - - Upload animation - - - - - - 220 - 160 - 131 - 41 - - - - color: red - - - - - <html><head/><body><p><span style=" font-size:12pt;">Disconnect</span></p></body></html> - - - Qt::AlignCenter - - - - - - 230 - 140 - 111 - 20 - - - - Statement swarm - - - Qt::AlignCenter - - - - - - 220 - 440 - 141 - 51 - - - - - - - Start animation - - - - - - 0 - -1 - 1280 - 701 - - - - <html><head/><body><p><img src=":/back/back.png"/></p></body></html> - - - - - - 620 - 110 - 111 - 40 - - - - - - - Safty check - - - - - - 620 - 160 - 111 - 40 - - - - - - - Synchronize - - - - - - 220 - 200 - 141 - 51 - - - - color:rgb(30, 30, 30) - - - <html><head/><body><p align="center"><span style=" font-size:16pt;"/></p></body></html> - - - back_label - take_off_button - land_all_button - disarm_all_button - take_off_n_button - land_n_button - disarm_n_button - take_off_spinBox - land_spinBox - disarm_spinBox - control_console_label - turn_on_led_button - turn_off_led_button - stop_swarm_but - connect_button - swarm_size_spinBox - swarm_size_label - send_command_label - console_textEdit - show_3d_scene_button - upload_animation_button - state_label - statement_swarm_label - start_animation_button - safty_button - synch_button - time_to_start_label - - - - - 0 - 0 - 1280 - 23 - - - - - - - - - - diff --git a/Server/gui/telem.qrc b/Server/gui/telem.qrc deleted file mode 100755 index 5a64fa3..0000000 --- a/Server/gui/telem.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - telem_bakground.png - - diff --git a/Server/gui/telem_bakground.png b/Server/gui/telem_bakground.png deleted file mode 100755 index 31e78529683f1d9ac4ce5d158d84d825c4d31b5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1027 zcmeAS@N?(olHy`uVBq!ia0y~yU{V9JKX5Ps$=x9qAPL6eAa^H*b?0PW0y!+{j=qiz z3>*8o|0J>k`J4qFk;M!Qe1}1p@p%4<6b1(78J;eVAr*0NZ*3GjtRTSP_(V%{qFu(B z#w$$eXDiGfKK}neXx-lL3=N;{&T})gd-5>|o@7)|vSe^kVQ=Vo!XPkFhCyi(vx7?! zLx;zpmIMX>1H*&8>nxue7u}0`Ew|<`@0`c&I{)o|+A$0P=MSyG9(65c`QwO0d|@4* U7I#W$2q@Wly85}Sb4q9e0P@2H0RR91 diff --git a/Server/gui/telemetry.ui b/Server/gui/telemetry.ui deleted file mode 100755 index 496691c..0000000 --- a/Server/gui/telemetry.ui +++ /dev/null @@ -1,536 +0,0 @@ - - - Dialog - - - - 0 - 0 - 550 - 240 - - - - - 550 - 240 - - - - - 550 - 240 - - - - Telemetry - - - - - 80 - 20 - 91 - 20 - - - - - 11 - - - - Copter - - - Qt::AlignCenter - - - - - - 10 - 10 - 93 - 41 - - - - Go - - - - - - 160 - 20 - 42 - 22 - - - - - - - 10 - 100 - 21 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">x=</span></p></body></html> - - - Qt::AlignCenter - - - - - - 10 - 150 - 21 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">y=</span></p></body></html> - - - Qt::AlignCenter - - - - - - 10 - 200 - 21 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">z=</span></p></body></html> - - - Qt::AlignCenter - - - - - - 40 - 200 - 51 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 40 - 100 - 51 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 40 - 150 - 51 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 470 - 130 - 71 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">MANUALE</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 470 - 100 - 71 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">False</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 400 - 170 - 61 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">farme id=</span><br/></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 400 - 100 - 51 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">armed=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 470 - 170 - 71 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">aruco_map</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 400 - 130 - 51 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">mode=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 470 - 200 - 71 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 400 - 200 - 51 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">voltage=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 190 - 200 - 61 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 140 - 100 - 31 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">yaw=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 140 - 150 - 41 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">pitch=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 140 - 200 - 31 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">roll=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 190 - 150 - 61 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 190 - 100 - 61 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 270 - 150 - 31 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">vy=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 320 - 100 - 61 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 270 - 200 - 31 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">vz=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 320 - 150 - 61 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 320 - 200 - 61 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">0.000</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 270 - 100 - 31 - 16 - - - - <html><head/><body><p><span style=" color:#c8c8c8;">vx=</span></p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 0 - 0 - 551 - 241 - - - - <html><head/><body><p><img src=":/telem/telem_bakground.png"/></p></body></html> - - - back - copter_text - go_pushButton - number_spinBox - x_1 - y_1 - z_1 - z_2 - x_2 - y_2 - mode_2 - armed_2 - frame_id_1 - armed_1 - frame_id_2 - mode_1 - voltage_2 - voltage_1 - roll_2 - yaw_1 - pitch_1 - roll_1 - pitch_2 - yaw2 - vy_1 - vx_2 - vz_1 - vy_2 - vz_2 - vx_1 - - - - - - diff --git a/Server/gui_telem.py b/Server/gui_telem.py deleted file mode 100644 index a38ded1..0000000 --- a/Server/gui_telem.py +++ /dev/null @@ -1,214 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'telemetry.ui' -# -# Created by: PyQt5 UI code generator 5.11.3 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(550, 240) - Dialog.setMinimumSize(QtCore.QSize(550, 240)) - Dialog.setMaximumSize(QtCore.QSize(550, 240)) - self.copter_text = QtWidgets.QLabel(Dialog) - self.copter_text.setGeometry(QtCore.QRect(80, 20, 91, 20)) - font = QtGui.QFont() - font.setPointSize(11) - self.copter_text.setFont(font) - self.copter_text.setAlignment(QtCore.Qt.AlignCenter) - self.copter_text.setObjectName("copter_text") - self.go_pushButton = QtWidgets.QPushButton(Dialog) - self.go_pushButton.setGeometry(QtCore.QRect(10, 10, 93, 41)) - self.go_pushButton.setObjectName("go_pushButton") - self.number_spinBox = QtWidgets.QSpinBox(Dialog) - self.number_spinBox.setGeometry(QtCore.QRect(160, 20, 42, 22)) - self.number_spinBox.setObjectName("number_spinBox") - self.x_1 = QtWidgets.QLabel(Dialog) - self.x_1.setGeometry(QtCore.QRect(10, 100, 21, 16)) - self.x_1.setAlignment(QtCore.Qt.AlignCenter) - self.x_1.setObjectName("x_1") - self.y_1 = QtWidgets.QLabel(Dialog) - self.y_1.setGeometry(QtCore.QRect(10, 150, 21, 16)) - self.y_1.setAlignment(QtCore.Qt.AlignCenter) - self.y_1.setObjectName("y_1") - self.z_1 = QtWidgets.QLabel(Dialog) - self.z_1.setGeometry(QtCore.QRect(10, 200, 21, 16)) - self.z_1.setAlignment(QtCore.Qt.AlignCenter) - self.z_1.setObjectName("z_1") - self.z_2 = QtWidgets.QLabel(Dialog) - self.z_2.setGeometry(QtCore.QRect(40, 200, 51, 16)) - self.z_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.z_2.setObjectName("z_2") - self.x_2 = QtWidgets.QLabel(Dialog) - self.x_2.setGeometry(QtCore.QRect(40, 100, 51, 16)) - self.x_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.x_2.setObjectName("x_2") - self.y_2 = QtWidgets.QLabel(Dialog) - self.y_2.setGeometry(QtCore.QRect(40, 150, 51, 16)) - self.y_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.y_2.setObjectName("y_2") - self.mode_2 = QtWidgets.QLabel(Dialog) - self.mode_2.setGeometry(QtCore.QRect(470, 130, 71, 16)) - self.mode_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.mode_2.setObjectName("mode_2") - self.armed_2 = QtWidgets.QLabel(Dialog) - self.armed_2.setGeometry(QtCore.QRect(470, 100, 71, 16)) - self.armed_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.armed_2.setObjectName("armed_2") - self.frame_id_1 = QtWidgets.QLabel(Dialog) - self.frame_id_1.setGeometry(QtCore.QRect(400, 170, 61, 16)) - self.frame_id_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.frame_id_1.setObjectName("frame_id_1") - self.armed_1 = QtWidgets.QLabel(Dialog) - self.armed_1.setGeometry(QtCore.QRect(400, 100, 51, 16)) - self.armed_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.armed_1.setObjectName("armed_1") - self.frame_id_2 = QtWidgets.QLabel(Dialog) - self.frame_id_2.setGeometry(QtCore.QRect(470, 170, 71, 16)) - self.frame_id_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.frame_id_2.setObjectName("frame_id_2") - self.mode_1 = QtWidgets.QLabel(Dialog) - self.mode_1.setGeometry(QtCore.QRect(400, 130, 51, 16)) - self.mode_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.mode_1.setObjectName("mode_1") - self.voltage_2 = QtWidgets.QLabel(Dialog) - self.voltage_2.setGeometry(QtCore.QRect(470, 200, 71, 16)) - self.voltage_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.voltage_2.setObjectName("voltage_2") - self.voltage_1 = QtWidgets.QLabel(Dialog) - self.voltage_1.setGeometry(QtCore.QRect(400, 200, 51, 16)) - self.voltage_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.voltage_1.setObjectName("voltage_1") - self.roll_2 = QtWidgets.QLabel(Dialog) - self.roll_2.setGeometry(QtCore.QRect(190, 200, 61, 16)) - self.roll_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.roll_2.setObjectName("roll_2") - self.yaw_1 = QtWidgets.QLabel(Dialog) - self.yaw_1.setGeometry(QtCore.QRect(140, 100, 31, 16)) - self.yaw_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.yaw_1.setObjectName("yaw_1") - self.pitch_1 = QtWidgets.QLabel(Dialog) - self.pitch_1.setGeometry(QtCore.QRect(140, 150, 41, 16)) - self.pitch_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.pitch_1.setObjectName("pitch_1") - self.roll_1 = QtWidgets.QLabel(Dialog) - self.roll_1.setGeometry(QtCore.QRect(140, 200, 31, 16)) - self.roll_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.roll_1.setObjectName("roll_1") - self.pitch_2 = QtWidgets.QLabel(Dialog) - self.pitch_2.setGeometry(QtCore.QRect(190, 150, 61, 16)) - self.pitch_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.pitch_2.setObjectName("pitch_2") - self.yaw2 = QtWidgets.QLabel(Dialog) - self.yaw2.setGeometry(QtCore.QRect(190, 100, 61, 16)) - self.yaw2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.yaw2.setObjectName("yaw2") - self.vy_1 = QtWidgets.QLabel(Dialog) - self.vy_1.setGeometry(QtCore.QRect(270, 150, 31, 16)) - self.vy_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.vy_1.setObjectName("vy_1") - self.vx_2 = QtWidgets.QLabel(Dialog) - self.vx_2.setGeometry(QtCore.QRect(320, 100, 61, 16)) - self.vx_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.vx_2.setObjectName("vx_2") - self.vz_1 = QtWidgets.QLabel(Dialog) - self.vz_1.setGeometry(QtCore.QRect(270, 200, 31, 16)) - self.vz_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.vz_1.setObjectName("vz_1") - self.vy_2 = QtWidgets.QLabel(Dialog) - self.vy_2.setGeometry(QtCore.QRect(320, 150, 61, 16)) - self.vy_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.vy_2.setObjectName("vy_2") - self.vz_2 = QtWidgets.QLabel(Dialog) - self.vz_2.setGeometry(QtCore.QRect(320, 200, 61, 16)) - self.vz_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.vz_2.setObjectName("vz_2") - self.vx_1 = QtWidgets.QLabel(Dialog) - self.vx_1.setGeometry(QtCore.QRect(270, 100, 31, 16)) - self.vx_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.vx_1.setObjectName("vx_1") - self.back = QtWidgets.QLabel(Dialog) - self.back.setGeometry(QtCore.QRect(0, 0, 551, 241)) - self.back.setObjectName("back") - self.back.raise_() - self.copter_text.raise_() - self.go_pushButton.raise_() - self.number_spinBox.raise_() - self.x_1.raise_() - self.y_1.raise_() - self.z_1.raise_() - self.z_2.raise_() - self.x_2.raise_() - self.y_2.raise_() - self.mode_2.raise_() - self.armed_2.raise_() - self.frame_id_1.raise_() - self.armed_1.raise_() - self.frame_id_2.raise_() - self.mode_1.raise_() - self.voltage_2.raise_() - self.voltage_1.raise_() - self.roll_2.raise_() - self.yaw_1.raise_() - self.pitch_1.raise_() - self.roll_1.raise_() - self.pitch_2.raise_() - self.yaw2.raise_() - self.vy_1.raise_() - self.vx_2.raise_() - self.vz_1.raise_() - self.vy_2.raise_() - self.vz_2.raise_() - self.vx_1.raise_() - - self.retranslateUi(Dialog) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Telemetry")) - self.copter_text.setText(_translate("Dialog", "Copter")) - self.go_pushButton.setText(_translate("Dialog", "Go")) - self.x_1.setText(_translate("Dialog", "

x=

")) - self.y_1.setText(_translate("Dialog", "

y=

")) - self.z_1.setText(_translate("Dialog", "

z=

")) - self.z_2.setText(_translate("Dialog", "

0.000

")) - self.x_2.setText(_translate("Dialog", "

0.000

")) - self.y_2.setText(_translate("Dialog", "

0.000

")) - self.mode_2.setText(_translate("Dialog", "

MANUALE

")) - self.armed_2.setText(_translate("Dialog", "

False

")) - self.frame_id_1.setText(_translate("Dialog", "

farme id=

")) - self.armed_1.setText(_translate("Dialog", "

armed=

")) - self.frame_id_2.setText(_translate("Dialog", "

aruco_map

")) - self.mode_1.setText(_translate("Dialog", "

mode=

")) - self.voltage_2.setText(_translate("Dialog", "

0.000

")) - self.voltage_1.setText(_translate("Dialog", "

voltage=

")) - self.roll_2.setText(_translate("Dialog", "

0.000

")) - self.yaw_1.setText(_translate("Dialog", "

yaw=

")) - self.pitch_1.setText(_translate("Dialog", "

pitch=

")) - self.roll_1.setText(_translate("Dialog", "

roll=

")) - self.pitch_2.setText(_translate("Dialog", "

0.000

")) - self.yaw2.setText(_translate("Dialog", "

0.000

")) - self.vy_1.setText(_translate("Dialog", "

vy=

")) - self.vx_2.setText(_translate("Dialog", "

0.000

")) - self.vz_1.setText(_translate("Dialog", "

vz=

")) - self.vy_2.setText(_translate("Dialog", "

0.000

")) - self.vz_2.setText(_translate("Dialog", "

0.000

")) - self.vx_1.setText(_translate("Dialog", "

vx=

")) - self.back.setText(_translate("Dialog", "

")) - -import telem_rc - -if __name__ == "__main__": - import sys - app = QtWidgets.QApplication(sys.argv) - Dialog = QtWidgets.QDialog() - ui = Ui_Dialog() - ui.setupUi(Dialog) - Dialog.show() - sys.exit(app.exec_()) - diff --git a/Server/main_gui.py b/Server/main_gui.py deleted file mode 100644 index 75fc44b..0000000 --- a/Server/main_gui.py +++ /dev/null @@ -1,203 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'gui.ui' -# -# Created by: PyQt5 UI code generator 5.11.3 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - MainWindow.setObjectName("MainWindow") - MainWindow.resize(1280, 720) - MainWindow.setMinimumSize(QtCore.QSize(1280, 720)) - MainWindow.setMaximumSize(QtCore.QSize(1280, 720)) - self.centralwidget = QtWidgets.QWidget(MainWindow) - self.centralwidget.setObjectName("centralwidget") - self.take_off_button = QtWidgets.QPushButton(self.centralwidget) - self.take_off_button.setGeometry(QtCore.QRect(760, 70, 100, 40)) - self.take_off_button.setObjectName("take_off_button") - self.land_all_button = QtWidgets.QPushButton(self.centralwidget) - self.land_all_button.setGeometry(QtCore.QRect(890, 70, 91, 40)) - self.land_all_button.setObjectName("land_all_button") - self.disarm_all_button = QtWidgets.QPushButton(self.centralwidget) - self.disarm_all_button.setGeometry(QtCore.QRect(1010, 70, 101, 40)) - self.disarm_all_button.setStyleSheet("background-color: red\n" -"") - self.disarm_all_button.setObjectName("disarm_all_button") - self.take_off_n_button = QtWidgets.QPushButton(self.centralwidget) - self.take_off_n_button.setGeometry(QtCore.QRect(760, 150, 100, 40)) - self.take_off_n_button.setObjectName("take_off_n_button") - self.land_n_button = QtWidgets.QPushButton(self.centralwidget) - self.land_n_button.setGeometry(QtCore.QRect(890, 150, 91, 40)) - self.land_n_button.setStyleSheet("") - self.land_n_button.setObjectName("land_n_button") - self.disarm_n_button = QtWidgets.QPushButton(self.centralwidget) - self.disarm_n_button.setGeometry(QtCore.QRect(1010, 150, 101, 40)) - self.disarm_n_button.setStyleSheet("background-color: red\n" -"") - self.disarm_n_button.setObjectName("disarm_n_button") - self.take_off_spinBox = QtWidgets.QSpinBox(self.centralwidget) - self.take_off_spinBox.setGeometry(QtCore.QRect(790, 120, 50, 22)) - self.take_off_spinBox.setObjectName("take_off_spinBox") - self.land_spinBox = QtWidgets.QSpinBox(self.centralwidget) - self.land_spinBox.setGeometry(QtCore.QRect(910, 120, 50, 22)) - self.land_spinBox.setObjectName("land_spinBox") - self.disarm_spinBox = QtWidgets.QSpinBox(self.centralwidget) - self.disarm_spinBox.setGeometry(QtCore.QRect(1040, 120, 50, 22)) - self.disarm_spinBox.setObjectName("disarm_spinBox") - self.control_console_label = QtWidgets.QLabel(self.centralwidget) - self.control_console_label.setGeometry(QtCore.QRect(840, 20, 200, 20)) - self.control_console_label.setAlignment(QtCore.Qt.AlignCenter) - self.control_console_label.setObjectName("control_console_label") - self.turn_on_led_button = QtWidgets.QPushButton(self.centralwidget) - self.turn_on_led_button.setGeometry(QtCore.QRect(1140, 60, 100, 61)) - self.turn_on_led_button.setStyleSheet("") - self.turn_on_led_button.setObjectName("turn_on_led_button") - self.turn_off_led_button = QtWidgets.QPushButton(self.centralwidget) - self.turn_off_led_button.setGeometry(QtCore.QRect(1140, 140, 100, 61)) - self.turn_off_led_button.setObjectName("turn_off_led_button") - self.stop_swarm_but = QtWidgets.QPushButton(self.centralwidget) - self.stop_swarm_but.setGeometry(QtCore.QRect(220, 510, 141, 51)) - self.stop_swarm_but.setStyleSheet("") - self.stop_swarm_but.setObjectName("stop_swarm_but") - self.connect_button = QtWidgets.QPushButton(self.centralwidget) - self.connect_button.setGeometry(QtCore.QRect(620, 60, 111, 40)) - self.connect_button.setStyleSheet("") - self.connect_button.setObjectName("connect_button") - self.swarm_size_spinBox = QtWidgets.QSpinBox(self.centralwidget) - self.swarm_size_spinBox.setGeometry(QtCore.QRect(260, 80, 50, 20)) - self.swarm_size_spinBox.setObjectName("swarm_size_spinBox") - self.swarm_size_label = QtWidgets.QLabel(self.centralwidget) - self.swarm_size_label.setGeometry(QtCore.QRect(240, 50, 100, 20)) - self.swarm_size_label.setAlignment(QtCore.Qt.AlignCenter) - self.swarm_size_label.setObjectName("swarm_size_label") - self.send_command_label = QtWidgets.QLabel(self.centralwidget) - self.send_command_label.setGeometry(QtCore.QRect(840, 260, 200, 20)) - self.send_command_label.setAlignment(QtCore.Qt.AlignCenter) - self.send_command_label.setObjectName("send_command_label") - self.console_textEdit = QtWidgets.QTextEdit(self.centralwidget) - self.console_textEdit.setGeometry(QtCore.QRect(640, 290, 591, 271)) - self.console_textEdit.setStyleSheet("background-color: rgb(1, 36, 86)") - self.console_textEdit.setObjectName("console_textEdit") - self.show_3d_scene_button = QtWidgets.QPushButton(self.centralwidget) - self.show_3d_scene_button.setGeometry(QtCore.QRect(220, 300, 141, 51)) - self.show_3d_scene_button.setStyleSheet("") - self.show_3d_scene_button.setObjectName("show_3d_scene_button") - self.upload_animation_button = QtWidgets.QPushButton(self.centralwidget) - self.upload_animation_button.setGeometry(QtCore.QRect(220, 370, 141, 51)) - self.upload_animation_button.setStyleSheet("") - self.upload_animation_button.setObjectName("upload_animation_button") - self.state_label = QtWidgets.QLabel(self.centralwidget) - self.state_label.setGeometry(QtCore.QRect(220, 160, 131, 41)) - self.state_label.setStyleSheet("color: red\n" -"\n" -"") - self.state_label.setAlignment(QtCore.Qt.AlignCenter) - self.state_label.setObjectName("state_label") - self.statement_swarm_label = QtWidgets.QLabel(self.centralwidget) - self.statement_swarm_label.setGeometry(QtCore.QRect(230, 140, 111, 20)) - self.statement_swarm_label.setAlignment(QtCore.Qt.AlignCenter) - self.statement_swarm_label.setObjectName("statement_swarm_label") - self.start_animation_button = QtWidgets.QPushButton(self.centralwidget) - self.start_animation_button.setGeometry(QtCore.QRect(220, 440, 141, 51)) - self.start_animation_button.setStyleSheet("") - self.start_animation_button.setObjectName("start_animation_button") - self.back_label = QtWidgets.QLabel(self.centralwidget) - self.back_label.setGeometry(QtCore.QRect(0, -1, 1280, 701)) - self.back_label.setObjectName("back_label") - self.safty_button = QtWidgets.QPushButton(self.centralwidget) - self.safty_button.setGeometry(QtCore.QRect(620, 110, 111, 40)) - self.safty_button.setStyleSheet("") - self.safty_button.setObjectName("safty_button") - self.synch_button = QtWidgets.QPushButton(self.centralwidget) - self.synch_button.setGeometry(QtCore.QRect(620, 160, 111, 40)) - self.synch_button.setStyleSheet("") - self.synch_button.setObjectName("synch_button") - self.time_to_start_label = QtWidgets.QLabel(self.centralwidget) - self.time_to_start_label.setGeometry(QtCore.QRect(220, 200, 141, 51)) - self.time_to_start_label.setStyleSheet("color:rgb(30, 30, 30)") - self.time_to_start_label.setObjectName("time_to_start_label") - self.back_label.raise_() - self.take_off_button.raise_() - self.land_all_button.raise_() - self.disarm_all_button.raise_() - self.take_off_n_button.raise_() - self.land_n_button.raise_() - self.disarm_n_button.raise_() - self.take_off_spinBox.raise_() - self.land_spinBox.raise_() - self.disarm_spinBox.raise_() - self.control_console_label.raise_() - self.turn_on_led_button.raise_() - self.turn_off_led_button.raise_() - self.stop_swarm_but.raise_() - self.connect_button.raise_() - self.swarm_size_spinBox.raise_() - self.swarm_size_label.raise_() - self.send_command_label.raise_() - self.console_textEdit.raise_() - self.show_3d_scene_button.raise_() - self.upload_animation_button.raise_() - self.state_label.raise_() - self.statement_swarm_label.raise_() - self.start_animation_button.raise_() - self.safty_button.raise_() - self.synch_button.raise_() - self.time_to_start_label.raise_() - MainWindow.setCentralWidget(self.centralwidget) - self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1280, 23)) - self.menubar.setObjectName("menubar") - MainWindow.setMenuBar(self.menubar) - self.statusbar = QtWidgets.QStatusBar(MainWindow) - self.statusbar.setObjectName("statusbar") - MainWindow.setStatusBar(self.statusbar) - - self.retranslateUi(MainWindow) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "Drone Swarm")) - self.take_off_button.setText(_translate("MainWindow", "Take off all")) - self.land_all_button.setText(_translate("MainWindow", "Land all")) - self.disarm_all_button.setText(_translate("MainWindow", "Disarm all")) - self.take_off_n_button.setText(_translate("MainWindow", "Take off n")) - self.land_n_button.setText(_translate("MainWindow", "Land n")) - self.disarm_n_button.setText(_translate("MainWindow", "Disarm n")) - self.control_console_label.setText(_translate("MainWindow", "

Control console

")) - self.turn_on_led_button.setText(_translate("MainWindow", "Turn on Leds")) - self.turn_off_led_button.setText(_translate("MainWindow", "Turn off Leds")) - self.stop_swarm_but.setText(_translate("MainWindow", "Stop swarm")) - self.connect_button.setText(_translate("MainWindow", "Connect")) - self.swarm_size_label.setText(_translate("MainWindow", "

Swarm Size

")) - self.send_command_label.setText(_translate("MainWindow", "

Send command

")) - self.console_textEdit.setHtml(_translate("MainWindow", "\n" -"\n" -"

...

")) - self.show_3d_scene_button.setText(_translate("MainWindow", "Show 3d scene")) - self.upload_animation_button.setText(_translate("MainWindow", "Upload animation")) - self.state_label.setText(_translate("MainWindow", "

Disconnect

")) - self.statement_swarm_label.setText(_translate("MainWindow", "Statement swarm")) - self.start_animation_button.setText(_translate("MainWindow", "Start animation")) - self.back_label.setText(_translate("MainWindow", "

")) - self.safty_button.setText(_translate("MainWindow", "Safty check")) - self.synch_button.setText(_translate("MainWindow", "Synchronize")) - self.time_to_start_label.setText(_translate("MainWindow", "

")) - -import back_1_rc - -if __name__ == "__main__": - import sys - app = QtWidgets.QApplication(sys.argv) - MainWindow = QtWidgets.QMainWindow() - ui = Ui_MainWindow() - ui.setupUi(MainWindow) - MainWindow.show() - sys.exit(app.exec_()) - diff --git a/Server/server_config.ini b/Server/server_config.ini new file mode 100644 index 0000000..061617e --- /dev/null +++ b/Server/server_config.ini @@ -0,0 +1,11 @@ +[SERVER] +port = 25000 +buffer_size = 1024 + +[NTP] +host = ntp1.stratum2.ru +port = 123 +#pool.ntp.org + +[FILETRANSFER] +animation = animation.csv \ No newline at end of file diff --git a/Server/telem_rc.py b/Server/telem_rc.py deleted file mode 100644 index 1cc6cff..0000000 --- a/Server/telem_rc.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- - -# Resource object code -# -# Created by: The Resource Compiler for PyQt5 (Qt v5.11.2) -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore - -qt_resource_data = b"\ -\x00\x00\x00\xe4\ -\x00\ -\x00\x04\x03\x78\x9c\xeb\x0c\xf0\x73\xe7\xe5\x92\xe2\x62\x60\x60\ -\xe0\xf5\xf4\x70\x09\x62\x60\x60\x52\x03\xb2\x3f\x70\x30\x01\xc9\ -\xdd\x21\x16\x20\x09\xc6\xe2\x20\x77\x27\x86\x75\xe7\x64\x5e\x02\ -\x39\x2c\xe9\x8e\xbe\x8e\x0c\x0c\x1b\xfb\xb9\xff\x24\xb2\x02\xf9\ -\x9c\x05\x1e\x91\xc5\x0c\x0c\x7c\x87\x41\x98\xf1\x78\xfe\x8a\x14\ -\x06\x06\xe6\x19\x9e\x2e\x8e\x21\x15\x71\x6f\x6f\x6d\x14\x3c\xac\ -\x20\xc0\xe0\xf8\x44\x4b\x73\xa2\x5d\xc6\x99\xc6\x2b\x4c\xe9\x67\ -\x2b\xcc\x1f\x3e\xfe\xff\x40\x68\xdd\xde\xef\x0c\x0d\x9f\xed\xce\ -\x73\x33\xb4\x7b\xf2\x31\x08\x9e\x64\x54\x50\xb2\x64\x70\x51\x61\ -\x6f\xe8\x78\xc2\x20\x30\x51\x86\x41\x69\x12\xb3\x83\x4b\x11\x43\ -\x87\xc7\xa0\x96\x64\x00\x81\x07\x7b\xd7\x59\x3e\x37\x2e\xba\x17\ -\xf5\x5a\x6e\xcd\x5f\xde\x39\x8f\xdb\x75\xfe\xdb\xff\xb4\x63\x18\ -\x1c\x2e\x1c\x95\x1c\x95\x84\x4a\x1e\x91\x88\x2f\xac\xe3\xd3\xe2\ -\x4e\x09\x0d\x01\x25\x5b\x4f\x57\x3f\x97\x75\x4e\x09\x4d\x00\xf2\ -\xc3\x05\x01\ -" - -qt_resource_name = b"\ -\x00\x05\ -\x00\x7a\xc2\xbd\ -\x00\x74\ -\x00\x65\x00\x6c\x00\x65\x00\x6d\ -\x00\x13\ -\x08\x4f\x8b\x27\ -\x00\x74\ -\x00\x65\x00\x6c\x00\x65\x00\x6d\x00\x5f\x00\x62\x00\x61\x00\x6b\x00\x67\x00\x72\x00\x6f\x00\x75\x00\x6e\x00\x64\x00\x2e\x00\x70\ -\x00\x6e\x00\x67\ -" - -qt_resource_struct_v1 = b"\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x10\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\ -" - -qt_resource_struct_v2 = b"\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ -\x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x10\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x64\xac\x7c\x9c\xca\ -" - -qt_version = [int(v) for v in QtCore.qVersion().split('.')] -if qt_version < [5, 8, 0]: - rcc_version = 1 - qt_resource_struct = qt_resource_struct_v1 -else: - rcc_version = 2 - qt_resource_struct = qt_resource_struct_v2 - -def qInitResources(): - QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) - -def qCleanupResources(): - QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) - -qInitResources() From 1c285786adb2893b7557d2f4b89c0566c79602f7 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sat, 19 Jan 2019 20:45:07 +0300 Subject: [PATCH 03/27] Import and name fix --- Drone/{Client.py => client.py} | 4 +- Server/{Server.py => server.py} | 578 ++++++++++++++++---------------- 2 files changed, 291 insertions(+), 291 deletions(-) rename Drone/{Client.py => client.py} (99%) mode change 100755 => 100644 rename Server/{Server.py => server.py} (96%) diff --git a/Drone/Client.py b/Drone/client.py old mode 100755 new mode 100644 similarity index 99% rename from Drone/Client.py rename to Drone/client.py index 8b1a7b5..304115f --- a/Drone/Client.py +++ b/Drone/client.py @@ -8,9 +8,9 @@ import threading import ConfigParser from contextlib import closing -#import rospy +import rospy -#import play_animation +import play_animation random.seed() diff --git a/Server/Server.py b/Server/server.py similarity index 96% rename from Server/Server.py rename to Server/server.py index e23082f..8711a49 100644 --- a/Server/Server.py +++ b/Server/server.py @@ -1,289 +1,289 @@ -from tkinter import * -from tkinter import ttk -from tkinter import filedialog -import ttkwidgets - -import os -import sys -import glob -import time -import struct -import socket -import threading -import collections -import configparser - -# All imports sorted in pyramid - - -def auto_connect(): - while True: - ServerSocket.listen(1) - c, addr = ServerSocket.accept() - print("Got connection from:", str(addr)) - #client_thread = threading.Thread(target=on_new_client, args=(c, addr)) - #client_thread.start() - - if not any(client_addr == addr[0] for client_addr in Client.clients.keys()): - client = Client(addr[0]) - print("New client") - else: - print("Reconnected client") - Client.clients[addr[0]].connect(c, addr) - - -NTP_DELTA = 2208988800 # 1970-01-01 00:00:00 -NTP_QUERY = b'\x1b' + bytes(47) - - -def get_ntp_time(ntp_host, ntp_port): - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: - s.sendto(NTP_QUERY, (ntp_host, ntp_port)) - msg, _ = s.recvfrom(1024) - return int.from_bytes(msg[-8:], 'big') / 2 ** 32 - NTP_DELTA - - -def requires_connect(f): - def wrapper(*args, **kwargs): - if args[0].connected: - return f(*args, **kwargs) - else: - print("Function requires client to be connected!") - return wrapper - - -class Client: - clients = {} - - def __init__(self, ip): - self.socket = None - self.addr = None - - self._send_queue = collections.deque() - self._received_queue = collections.deque() - self._request_queue = collections.OrderedDict() - - self.copter_id = None - self.malfunction = False - - Client.clients[ip] = self - - self.connected = False - - def connect(self, client_socket, client_addr): - print("Client connected") - self._send_queue = collections.deque() # comment for resuming queue after reconnection - - self.socket = client_socket - self.addr = client_addr - - self.socket.setblocking(0) - self.connected = True - client_thread = threading.Thread(target=self._run, args=()) - client_thread.start() - if self.copter_id is None: - self.copter_id = self.get_response("id") - print("Got copter id:", self.copter_id) - drone_list.insert("", "end", self.addr[0], text=self.copter_id) - - def _send_all(self, msg): - self.socket.sendall(struct.pack('>I', len(msg)) + msg) - - def _receive_all(self, n): - data = b'' - while len(data) < n: - packet = self.socket.recv(min(n - len(data), BUFFER_SIZE)) - if not packet: - return None - data += packet - return data - - def _receive_message(self): - raw_msglen = self._receive_all(4) - if not raw_msglen: - return None - msglen = struct.unpack('>I', raw_msglen)[0] - msg = self._receive_all(msglen) - return msg - - def _run(self): - while self.connected: - try: - if self._send_queue: - msg = self._send_queue.popleft() - print("Send", msg, "to", self.addr) - self._send_all(msg) - else: - msg = "ping" - #self._send_all(msg) - - try: # check if data in buffer - check = self.socket.recv(BUFFER_SIZE, socket.MSG_PEEK) - if check: - received = self._receive_message() - if received: - received = received.decode("UTF-8") - print("Recived", received, "from", self.addr) - command, args = Client.parse_command(received) - if command == "response": - for key, value in self._request_queue.items(): - if not value: - self._request_queue[key] = args[0] - print("Request successfully closed") - break - else: - self._received_queue.appendleft(received) - except socket.error: - pass - - except socket.error as e: - print("Client error, disconnected", e) - self.connected = False - self.socket.close() - break - # time.sleep(0.05) - - @staticmethod - def form_command(command: str, args=()): # Change for different protocol - return " ".join([command, *args]) - - @staticmethod - def parse_command(command_input): - args = command_input.split() - command = args.pop(0) - return command, args - - @requires_connect - def send(self, *messages): - for message in messages: - self._send_queue.append(bytes(message, "UTF-8")) - - @staticmethod - def broadcast(message, force_all=False): - for client in Client.clients.values(): - if (not client.malfunction) or force_all: - client.send(message) - - @requires_connect - def send_file(self, filepath, dest_filename): - print("Sending file ", dest_filename) - self.send(Client.form_command("writefile", (dest_filename,))) - file = open(filepath, 'rb') - chunk = file.read(BUFFER_SIZE) - while chunk: - self._send_queue.append(chunk) - chunk = file.read(BUFFER_SIZE) - file.close() - self.send(Client.form_command("/endoffile")) - print("File sent") - - @requires_connect - def get_response(self, requested_value): - self._request_queue[requested_value] = "" - self.send(Client.form_command("request", (requested_value, ))) - - while not self._request_queue[requested_value]: - pass - - return self._request_queue.pop(requested_value) - - -# UI functions -def stop_swarm(): - Client.broadcast("stop") # для тестирования - - -def send_animations(): - path = filedialog.askdirectory(title="Animation directory") - if path: - print("Selected directory:", path) - files = [file for file in glob.glob(path+'/*.csv')] - names = [os.path.basename(file).split(".")[0] for file in files] - print(files) - for file, name in zip(files, names): - for copter in Client.clients.values(): - if name == copter.copter_id: - copter.send_file(file, "animation.csv") # TODO config - else: - print("Filename not matches with any drone connected") - #dr = next(iter(Client.clients.values())) # костыль для тестирования - #ANS = dr.get_response("someshit") - #print(ANS) - - -def send_starttime(dt=60): - timenow = time.time() - print('Now:', time.ctime(timenow), "+ dt =", dt) - Client.broadcast(Client.form_command("starttime", (str(timenow+dt), ))) - - -# UI build here -root = Tk() -root.wm_title("Drone swarm operation server") -root.style = ttk.Style() -root.style.theme_use("vista") - -leftFrame = Frame(root) -leftFrame.grid(row=0, column=0, padx=10, pady=10) -rightFrame = Frame(root) -rightFrame.grid(row=0, column=1, padx=10, pady=10) - -drone_list = ttkwidgets.CheckboxTreeview(leftFrame, columns=("addr", "connected")) -#drone_list["columns"] = ("addr") -#drone_list.column("name") #width=100 -#drone_list.column("addr") -drone_list.heading("#0", text="Drone name") -drone_list.heading("#1", text="Connection adress") -drone_list.heading("#2", text="Connection status") -drone_list.pack() - -button_frame = Frame(leftFrame, borderwidth=1, relief="solid") -button_frame.pack(fill=BOTH, expand=True) - -stop_all_btn = ttk.Button(button_frame, text="Stop swarm", command=stop_swarm) -stop_all_btn.pack(side=RIGHT, padx=5, pady=5) - -send_animation_btn = ttk.Button(button_frame, text="Send animations", command=send_animations) -send_animation_btn.pack(side=RIGHT, padx=5, pady=5) - -send_starttime_btn = ttk.Button(button_frame, text="Start animation after...", command=send_starttime) -send_starttime_btn.pack(side=RIGHT, padx=5, pady=5) - - -def gui_update(): - time.sleep(0.1) - - -# reading config -config = configparser.ConfigParser() -config.read("server_config.ini") - -port = int(config['SERVER']['port']) -BUFFER_SIZE = int(config['SERVER']['buffer_size']) -NTP_HOST = config['NTP']['host'] -NTP_PORT = int(config['NTP']['port']) - - -ServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socket.socket() # -ServerSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) -host = socket.gethostname() -ip = socket.gethostbyname_ex(host)[-1] - -print('Server started on', host, ip, ":", port) -#print('Now:', time.ctime(get_ntp_time(NTP_HOST, NTP_PORT))) -print('Waiting for clients...') -ServerSocket.bind((ip[-1], port)) - -autoconnect_thread = threading.Thread(target=auto_connect) -autoconnect_thread.daemon = True -autoconnect_thread.start() - - -if __name__ == '__main__': - try: - mainloop() - except KeyboardInterrupt: - print("Stopping server by keyboard interrupt") - finally: - ServerSocket.close() - print("Server shutdown") +from tkinter import * +from tkinter import ttk +from tkinter import filedialog +import ttkwidgets + +import os +import sys +import glob +import time +import struct +import socket +import threading +import collections +import configparser + +# All imports sorted in pyramid + + +def auto_connect(): + while True: + ServerSocket.listen(1) + c, addr = ServerSocket.accept() + print("Got connection from:", str(addr)) + #client_thread = threading.Thread(target=on_new_client, args=(c, addr)) + #client_thread.start() + + if not any(client_addr == addr[0] for client_addr in Client.clients.keys()): + client = Client(addr[0]) + print("New client") + else: + print("Reconnected client") + Client.clients[addr[0]].connect(c, addr) + + +NTP_DELTA = 2208988800 # 1970-01-01 00:00:00 +NTP_QUERY = b'\x1b' + bytes(47) + + +def get_ntp_time(ntp_host, ntp_port): + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: + s.sendto(NTP_QUERY, (ntp_host, ntp_port)) + msg, _ = s.recvfrom(1024) + return int.from_bytes(msg[-8:], 'big') / 2 ** 32 - NTP_DELTA + + +def requires_connect(f): + def wrapper(*args, **kwargs): + if args[0].connected: + return f(*args, **kwargs) + else: + print("Function requires client to be connected!") + return wrapper + + +class Client: + clients = {} + + def __init__(self, ip): + self.socket = None + self.addr = None + + self._send_queue = collections.deque() + self._received_queue = collections.deque() + self._request_queue = collections.OrderedDict() + + self.copter_id = None + self.malfunction = False + + Client.clients[ip] = self + + self.connected = False + + def connect(self, client_socket, client_addr): + print("Client connected") + self._send_queue = collections.deque() # comment for resuming queue after reconnection + + self.socket = client_socket + self.addr = client_addr + + self.socket.setblocking(0) + self.connected = True + client_thread = threading.Thread(target=self._run, args=()) + client_thread.start() + if self.copter_id is None: + self.copter_id = self.get_response("id") + print("Got copter id:", self.copter_id) + drone_list.insert("", "end", self.addr[0], text=self.copter_id) + + def _send_all(self, msg): + self.socket.sendall(struct.pack('>I', len(msg)) + msg) + + def _receive_all(self, n): + data = b'' + while len(data) < n: + packet = self.socket.recv(min(n - len(data), BUFFER_SIZE)) + if not packet: + return None + data += packet + return data + + def _receive_message(self): + raw_msglen = self._receive_all(4) + if not raw_msglen: + return None + msglen = struct.unpack('>I', raw_msglen)[0] + msg = self._receive_all(msglen) + return msg + + def _run(self): + while self.connected: + try: + if self._send_queue: + msg = self._send_queue.popleft() + print("Send", msg, "to", self.addr) + self._send_all(msg) + else: + msg = "ping" + #self._send_all(msg) + + try: # check if data in buffer + check = self.socket.recv(BUFFER_SIZE, socket.MSG_PEEK) + if check: + received = self._receive_message() + if received: + received = received.decode("UTF-8") + print("Recived", received, "from", self.addr) + command, args = Client.parse_command(received) + if command == "response": + for key, value in self._request_queue.items(): + if not value: + self._request_queue[key] = args[0] + print("Request successfully closed") + break + else: + self._received_queue.appendleft(received) + except socket.error: + pass + + except socket.error as e: + print("Client error, disconnected", e) + self.connected = False + self.socket.close() + break + # time.sleep(0.05) + + @staticmethod + def form_command(command: str, args=()): # Change for different protocol + return " ".join([command, *args]) + + @staticmethod + def parse_command(command_input): + args = command_input.split() + command = args.pop(0) + return command, args + + @requires_connect + def send(self, *messages): + for message in messages: + self._send_queue.append(bytes(message, "UTF-8")) + + @staticmethod + def broadcast(message, force_all=False): + for client in Client.clients.values(): + if (not client.malfunction) or force_all: + client.send(message) + + @requires_connect + def send_file(self, filepath, dest_filename): + print("Sending file ", dest_filename) + self.send(Client.form_command("writefile", (dest_filename,))) + file = open(filepath, 'rb') + chunk = file.read(BUFFER_SIZE) + while chunk: + self._send_queue.append(chunk) + chunk = file.read(BUFFER_SIZE) + file.close() + self.send(Client.form_command("/endoffile")) + print("File sent") + + @requires_connect + def get_response(self, requested_value): + self._request_queue[requested_value] = "" + self.send(Client.form_command("request", (requested_value, ))) + + while not self._request_queue[requested_value]: + pass + + return self._request_queue.pop(requested_value) + + +# UI functions +def stop_swarm(): + Client.broadcast("stop") # для тестирования + + +def send_animations(): + path = filedialog.askdirectory(title="Animation directory") + if path: + print("Selected directory:", path) + files = [file for file in glob.glob(path+'/*.csv')] + names = [os.path.basename(file).split(".")[0] for file in files] + print(files) + for file, name in zip(files, names): + for copter in Client.clients.values(): + if name == copter.copter_id: + copter.send_file(file, "animation.csv") # TODO config + else: + print("Filename not matches with any drone connected") + #dr = next(iter(Client.clients.values())) # костыль для тестирования + #ANS = dr.get_response("someshit") + #print(ANS) + + +def send_starttime(dt=60): + timenow = time.time() + print('Now:', time.ctime(timenow), "+ dt =", dt) + Client.broadcast(Client.form_command("starttime", (str(timenow+dt), ))) + + +# UI build here +root = Tk() +root.wm_title("Drone swarm operation server") +root.style = ttk.Style() +root.style.theme_use("vista") + +leftFrame = Frame(root) +leftFrame.grid(row=0, column=0, padx=10, pady=10) +rightFrame = Frame(root) +rightFrame.grid(row=0, column=1, padx=10, pady=10) + +drone_list = ttkwidgets.CheckboxTreeview(leftFrame, columns=("addr", "connected")) +#drone_list["columns"] = ("addr") +#drone_list.column("name") #width=100 +#drone_list.column("addr") +drone_list.heading("#0", text="Drone name") +drone_list.heading("#1", text="Connection adress") +drone_list.heading("#2", text="Connection status") +drone_list.pack() + +button_frame = Frame(leftFrame, borderwidth=1, relief="solid") +button_frame.pack(fill=BOTH, expand=True) + +stop_all_btn = ttk.Button(button_frame, text="Stop swarm", command=stop_swarm) +stop_all_btn.pack(side=RIGHT, padx=5, pady=5) + +send_animation_btn = ttk.Button(button_frame, text="Send animations", command=send_animations) +send_animation_btn.pack(side=RIGHT, padx=5, pady=5) + +send_starttime_btn = ttk.Button(button_frame, text="Start animation after...", command=send_starttime) +send_starttime_btn.pack(side=RIGHT, padx=5, pady=5) + + +def gui_update(): + time.sleep(0.1) + + +# reading config +config = configparser.ConfigParser() +config.read("server_config.ini") + +port = int(config['SERVER']['port']) +BUFFER_SIZE = int(config['SERVER']['buffer_size']) +NTP_HOST = config['NTP']['host'] +NTP_PORT = int(config['NTP']['port']) + + +ServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socket.socket() # +ServerSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +host = socket.gethostname() +ip = socket.gethostbyname_ex(host)[-1] + +print('Server started on', host, ip, ":", port) +#print('Now:', time.ctime(get_ntp_time(NTP_HOST, NTP_PORT))) +print('Waiting for clients...') +ServerSocket.bind((ip[-1], port)) + +autoconnect_thread = threading.Thread(target=auto_connect) +autoconnect_thread.daemon = True +autoconnect_thread.start() + + +if __name__ == '__main__': + try: + mainloop() + except KeyboardInterrupt: + print("Stopping server by keyboard interrupt") + finally: + ServerSocket.close() + print("Server shutdown") From cba3284e5c37cecb5ce3f5bcccc074ee510bd0a1 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sat, 19 Jan 2019 20:57:30 +0300 Subject: [PATCH 04/27] Init fix --- Drone/play_animation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Drone/play_animation.py b/Drone/play_animation.py index 6289e8b..dcc3838 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -1,7 +1,7 @@ import time import csv from FlightLib.FlightLib import FlightLib -FlightLib.init('SingleCleverFlight') +#FlightLib.init('SingleCleverFlight') from FlightLib.FlightLib import LedLib animation_file_path = 'drone.csv' @@ -55,6 +55,8 @@ def frame(): if __name__ == '__main__': + FlightLib.init('SingleCleverFlight') + read_animation_file() takeoff() From e794b21883ac725410e58ef1f71360e76be5412f Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sat, 19 Jan 2019 21:01:57 +0300 Subject: [PATCH 05/27] Init fix --- Drone/client.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Drone/client.py b/Drone/client.py index 304115f..a3d08af 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -10,6 +10,10 @@ from contextlib import closing import rospy +from FlightLib.FlightLib import FlightLib +rospy.init_node('Swarm_client', anonymous=True) +from FlightLib.FlightLib import LedLib + import play_animation random.seed() From 8d3725d4f3d1bea9215dca0920634ba84a65e954 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sat, 19 Jan 2019 21:06:06 +0300 Subject: [PATCH 06/27] Threadingfix --- Drone/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Drone/client.py b/Drone/client.py index a3d08af..e7f30eb 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -120,7 +120,7 @@ running_animation_event = threading.Event() animation_thread = threading.Thread(target=animation_player, args=(running_animation_event, stop_animation_event)) -def start_animation(): +def start_animation(*args, **kwargs): play_animation.read_animation_file(animation_file) print("Starting animation!") resume_animation() From 28c1a56cbd4758a929a9e1d78b9aa55d2c69ae7a Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sat, 19 Jan 2019 21:11:14 +0300 Subject: [PATCH 07/27] Threadingfix --- Drone/{copter6349.csv => animation.csv} | 0 Server/server.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename Drone/{copter6349.csv => animation.csv} (100%) diff --git a/Drone/copter6349.csv b/Drone/animation.csv similarity index 100% rename from Drone/copter6349.csv rename to Drone/animation.csv diff --git a/Server/server.py b/Server/server.py index 8711a49..1764269 100644 --- a/Server/server.py +++ b/Server/server.py @@ -211,7 +211,7 @@ def send_animations(): #print(ANS) -def send_starttime(dt=60): +def send_starttime(dt=30): timenow = time.time() print('Now:', time.ctime(timenow), "+ dt =", dt) Client.broadcast(Client.form_command("starttime", (str(timenow+dt), ))) From b300db8601e12601cdc1da8f9458e9c010c8154a Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 20 Jan 2019 12:07:27 +0300 Subject: [PATCH 08/27] Leds off + takeoff fix --- Drone/client.py | 10 +++++++--- Drone/client_config.ini | 3 ++- Drone/play_animation.py | 21 +++++++++++++-------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Drone/client.py b/Drone/client.py index e7f30eb..bf94fdd 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -102,7 +102,7 @@ def animation_player(running_event, stop_event): print("Animation thread activated") rate = rospy.Rate(1000 / 100) play_animation.takeoff(TAKEOFF_HEIGHT) - for current_frame in play_animation.frame(): + for current_frame in play_animation.get_frames(): running_event.wait() if stop_event.is_set(): break @@ -165,6 +165,9 @@ if COPTER_ID == 'default': TAKEOFF_HEIGHT = float(config.get('COPTER', 'takeoff_height')) +USE_LEDS = bool(config.get('COPTER', 'use_leds')) +play_animation.USE_LEDS = USE_LEDS + print("Client started on copter:", COPTER_ID) print("NTP time:", time.ctime(get_ntp_time(NTP_HOST, NTP_PORT))) print("System time", time.ctime(time.time())) @@ -200,8 +203,9 @@ try: send_all(bytes(form_command("response", response))) print("Request responded with:", response) - except socket.error: - print("Connection lost... reconnecting") + except socket.error as e: + print("Connection lost due error:", e) + print("Reconnecting...") reconnect() print("Re-connection successful") except KeyboardInterrupt: diff --git a/Drone/client_config.ini b/Drone/client_config.ini index 71439a9..c121f7c 100644 --- a/Drone/client_config.ini +++ b/Drone/client_config.ini @@ -11,7 +11,8 @@ host = ntp1.stratum2.ru port = 123 [COPTER] -id = copter6349 +id = default takeoff_height = 1.75 takeoff_timeout = 7 +use_leds = True animation_file = animation.csv diff --git a/Drone/play_animation.py b/Drone/play_animation.py index dcc3838..62adbb9 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -6,17 +6,21 @@ from FlightLib.FlightLib import LedLib animation_file_path = 'drone.csv' frames = [] +USE_LEDS = True def takeoff(h=1.75): - LedLib.wipe_to(0, 255, 0) - FlightLib.takeoff(h) + if USE_LEDS: + LedLib.wipe_to(0, 255, 0) + FlightLib.takeoff(h, fixed_delay=True) def land(): - LedLib.rainbow() + if USE_LEDS: + LedLib.blink(0, 255, 0) FlightLib.land() - LedLib.off() + if USE_LEDS: + LedLib.off() def do_next_animation(current_frame): @@ -24,9 +28,10 @@ def do_next_animation(current_frame): round(float(current_frame['x']), 4), round(float(current_frame['y']), 4), round(float(current_frame['z']), 4), round(float(current_frame['yaw']), 4), speed=round(float(current_frame['speed']), 4) ) - LedLib.fill( - int(current_frame['green']), int(current_frame['red']), int(current_frame['blue']) - ) + if USE_LEDS: + LedLib.fill( + int(current_frame['green']), int(current_frame['red']), int(current_frame['blue']) + ) def read_animation_file(filepath=animation_file_path): @@ -49,7 +54,7 @@ def read_animation_file(filepath=animation_file_path): }) -def frame(): +def get_frames(): global frames return frames From 1549746da2041601ab6d8a6a7c5ade1d73e11155 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 20 Jan 2019 12:19:21 +0300 Subject: [PATCH 09/27] Interrupt fix --- Drone/client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Drone/client.py b/Drone/client.py index bf94fdd..ed746cd 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -202,7 +202,8 @@ try: response = COPTER_ID send_all(bytes(form_command("response", response))) print("Request responded with:", response) - + except InterruptedError: + print("Interrupted") except socket.error as e: print("Connection lost due error:", e) print("Reconnecting...") From aef815d8e356e2b5fd6e8c0f17efc79c9396f5da Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 20 Jan 2019 12:28:31 +0300 Subject: [PATCH 10/27] Interrupt fix --- Drone/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Drone/client.py b/Drone/client.py index ed746cd..d705c4c 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -202,7 +202,7 @@ try: response = COPTER_ID send_all(bytes(form_command("response", response))) print("Request responded with:", response) - except InterruptedError: + except KeyboardInterrupt: print("Interrupted") except socket.error as e: print("Connection lost due error:", e) From 62e6546656b97364dee2290f40e71f2942f51689 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 20 Jan 2019 12:38:54 +0300 Subject: [PATCH 11/27] Interrupt fix --- Drone/client.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Drone/client.py b/Drone/client.py index d705c4c..aed8783 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -4,6 +4,7 @@ import socket import struct import random import time +import errno import threading import ConfigParser from contextlib import closing @@ -202,13 +203,14 @@ try: response = COPTER_ID send_all(bytes(form_command("response", response))) print("Request responded with:", response) - except KeyboardInterrupt: - print("Interrupted") except socket.error as e: - print("Connection lost due error:", e) - print("Reconnecting...") - reconnect() - print("Re-connection successful") + if e.errno != errno.EINTR: + print("Connection lost due error:", e) + print("Reconnecting...") + reconnect() + print("Re-connection successful") + else: + print("Interrupted") except KeyboardInterrupt: print("Shutdown on keyboard interrupt") finally: From c0cf6911c3781881bcea622f7dd6c8d715af2f01 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 20 Jan 2019 12:44:58 +0300 Subject: [PATCH 12/27] Interrupt fix --- Drone/client.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Drone/client.py b/Drone/client.py index aed8783..e54de3b 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -211,6 +211,7 @@ try: print("Re-connection successful") else: print("Interrupted") + raise KeyboardInterrupt except KeyboardInterrupt: print("Shutdown on keyboard interrupt") finally: From c2b96a506c80ea3b482f6436bad92e09186cb7f5 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 20 Jan 2019 18:18:48 +0300 Subject: [PATCH 13/27] Interrupt fix --- Drone/client.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Drone/client.py b/Drone/client.py index e54de3b..342d473 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -193,6 +193,9 @@ try: dt = starttime - get_ntp_time(NTP_HOST, NTP_PORT) print("Until start:", dt) rospy.Timer(rospy.Duration(dt), start_animation, oneshot=True) + elif command == 'stop': + FlightLib.takeoff(2) + FlightLib.reach(5, 5, 2) elif command == 'request': request_target = args[0] print("Got request for:", request_target) From 321800e922339fc1a16945c05da147433a748b10 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 27 Jan 2019 18:04:02 +0300 Subject: [PATCH 14/27] Takeoff newfix --- Drone/client.py | 21 ++++++++++++++------- Drone/play_animation.py | 7 ++++--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Drone/client.py b/Drone/client.py index 342d473..aeb022b 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -12,7 +12,6 @@ from contextlib import closing import rospy from FlightLib.FlightLib import FlightLib -rospy.init_node('Swarm_client', anonymous=True) from FlightLib.FlightLib import LedLib import play_animation @@ -102,7 +101,8 @@ def write_to_config(section, option, value): def animation_player(running_event, stop_event): print("Animation thread activated") rate = rospy.Rate(1000 / 100) - play_animation.takeoff(TAKEOFF_HEIGHT) + first_frame = play_animation.get_frames()[0] + play_animation.takeoff(round(float(first_frame['x']), 4), round(float(first_frame['y']), 4), round(float(first_frame['z']), 4)) for current_frame in play_animation.get_frames(): running_event.wait() if stop_event.is_set(): @@ -118,13 +118,14 @@ def animation_player(running_event, stop_event): stop_animation_event = threading.Event() running_animation_event = threading.Event() -animation_thread = threading.Thread(target=animation_player, args=(running_animation_event, stop_animation_event)) def start_animation(*args, **kwargs): + animation_thread = threading.Thread(target=animation_player, args=(running_animation_event, stop_animation_event)) play_animation.read_animation_file(animation_file) print("Starting animation!") - resume_animation() + running_animation_event.set() + stop_animation_event.clear() animation_thread.start() @@ -142,7 +143,8 @@ def stop_animation(): stop_animation_event.set() running_animation_event.clear() print("Stopping animation") - animation_thread.join() +# animation_thread.join() + CONFIG_PATH = "client_config.ini" @@ -169,6 +171,10 @@ TAKEOFF_HEIGHT = float(config.get('COPTER', 'takeoff_height')) USE_LEDS = bool(config.get('COPTER', 'use_leds')) play_animation.USE_LEDS = USE_LEDS +rospy.init_node('Swarm_client', anonymous=True) +if USE_LEDS: + LedLib.init_led() + print("Client started on copter:", COPTER_ID) print("NTP time:", time.ctime(get_ntp_time(NTP_HOST, NTP_PORT))) print("System time", time.ctime(time.time())) @@ -194,8 +200,9 @@ try: print("Until start:", dt) rospy.Timer(rospy.Duration(dt), start_animation, oneshot=True) elif command == 'stop': - FlightLib.takeoff(2) - FlightLib.reach(5, 5, 2) + pass + #FlightLib.takeoff(2) + #FlightLib.reach(5, 5, 2) elif command == 'request': request_target = args[0] print("Got request for:", request_target) diff --git a/Drone/play_animation.py b/Drone/play_animation.py index 62adbb9..677a3b9 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -4,15 +4,15 @@ from FlightLib.FlightLib import FlightLib #FlightLib.init('SingleCleverFlight') from FlightLib.FlightLib import LedLib -animation_file_path = 'drone.csv' +animation_file_path = 'animation.csv' frames = [] USE_LEDS = True -def takeoff(h=1.75): +def takeoff(x, y, z): if USE_LEDS: LedLib.wipe_to(0, 255, 0) - FlightLib.takeoff(h, fixed_delay=True) + FlightLib.takeoff(x, y, z) def land(): @@ -61,6 +61,7 @@ def get_frames(): if __name__ == '__main__': FlightLib.init('SingleCleverFlight') + LedLib.init_led() read_animation_file() From e6bdcc40c0563b8ade0524e09cb8655bc415e52f Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 27 Jan 2019 18:46:24 +0300 Subject: [PATCH 15/27] f --- Drone/client.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Drone/client.py b/Drone/client.py index aeb022b..fb8836a 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -172,6 +172,7 @@ USE_LEDS = bool(config.get('COPTER', 'use_leds')) play_animation.USE_LEDS = USE_LEDS rospy.init_node('Swarm_client', anonymous=True) +print(USE_LEDS) if USE_LEDS: LedLib.init_led() From 9cb3f9b5c0ba4fd1d2d294f13944f8b02335b70a Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 27 Jan 2019 18:48:15 +0300 Subject: [PATCH 16/27] f --- Drone/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Drone/client.py b/Drone/client.py index fb8836a..19823ff 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -168,7 +168,7 @@ if COPTER_ID == 'default': TAKEOFF_HEIGHT = float(config.get('COPTER', 'takeoff_height')) -USE_LEDS = bool(config.get('COPTER', 'use_leds')) +USE_LEDS = config.getboolean('COPTER', 'use_leds') play_animation.USE_LEDS = USE_LEDS rospy.init_node('Swarm_client', anonymous=True) From 0b080c7189f874754a9a047c8491001c54dbfda1 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 27 Jan 2019 19:04:05 +0300 Subject: [PATCH 17/27] f --- Drone/play_animation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Drone/play_animation.py b/Drone/play_animation.py index 677a3b9..6b87331 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -61,7 +61,7 @@ def get_frames(): if __name__ == '__main__': FlightLib.init('SingleCleverFlight') - LedLib.init_led() + #LedLib.init_led() read_animation_file() From 58dbaa1f10442e79ff566836b2c547e4db07cdbd Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 27 Jan 2019 19:05:50 +0300 Subject: [PATCH 18/27] f --- Drone/play_animation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Drone/play_animation.py b/Drone/play_animation.py index 6b87331..1651f62 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -65,7 +65,8 @@ if __name__ == '__main__': read_animation_file() - takeoff() + first_frame = get_frames()[0] + takeoff(round(float(first_frame['x']), 4), round(float(first_frame['y']), 4), round(float(first_frame['z']), 4)) #FlightLib.reach() for frame in frames: time.sleep(0.1) From 9d390c64fe1815b1c189d330443b52345c3b2b75 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 27 Jan 2019 19:07:04 +0300 Subject: [PATCH 19/27] f --- Drone/play_animation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Drone/play_animation.py b/Drone/play_animation.py index 1651f62..e2477cc 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -65,7 +65,7 @@ if __name__ == '__main__': read_animation_file() - first_frame = get_frames()[0] + first_frame = frames[0] takeoff(round(float(first_frame['x']), 4), round(float(first_frame['y']), 4), round(float(first_frame['z']), 4)) #FlightLib.reach() for frame in frames: From 0dbce86bcf8dc312e591337b51654811b09b5e11 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 27 Jan 2019 19:12:45 +0300 Subject: [PATCH 20/27] f --- Drone/play_animation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Drone/play_animation.py b/Drone/play_animation.py index e2477cc..4204404 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -1,5 +1,6 @@ import time import csv +import rospy from FlightLib.FlightLib import FlightLib #FlightLib.init('SingleCleverFlight') from FlightLib.FlightLib import LedLib @@ -60,7 +61,7 @@ def get_frames(): if __name__ == '__main__': - FlightLib.init('SingleCleverFlight') + rospy.init_node('Animation_player', anonymous=True) #LedLib.init_led() read_animation_file() From 3ec62ddca130978a74bbd4a7c1af20d2701e18eb Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Sun, 27 Jan 2019 20:29:50 +0300 Subject: [PATCH 21/27] f --- Drone/play_animation.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Drone/play_animation.py b/Drone/play_animation.py index 4204404..e23b693 100644 --- a/Drone/play_animation.py +++ b/Drone/play_animation.py @@ -10,10 +10,10 @@ frames = [] USE_LEDS = True -def takeoff(x, y, z): +def takeoff(): #x, y, z if USE_LEDS: LedLib.wipe_to(0, 255, 0) - FlightLib.takeoff(x, y, z) + FlightLib.takeoff() def land(): @@ -62,12 +62,13 @@ def get_frames(): if __name__ == '__main__': rospy.init_node('Animation_player', anonymous=True) - #LedLib.init_led() + LedLib.init_led() read_animation_file() - first_frame = frames[0] - takeoff(round(float(first_frame['x']), 4), round(float(first_frame['y']), 4), round(float(first_frame['z']), 4)) + #first_frame = frames[0] + #takeoff(round(float(first_frame['x']), 4), round(float(first_frame['y']), 4), round(float(first_frame['z']), 4)) + takeoff() #FlightLib.reach() for frame in frames: time.sleep(0.1) From bf0e1ab8d5b370f31e7f481683d335df3b190929 Mon Sep 17 00:00:00 2001 From: Artem30801 Date: Mon, 28 Jan 2019 14:09:41 +0300 Subject: [PATCH 22/27] Addded blender addon --- .gitmodules | 3 +++ Drone/client.py | 1 - Server/server.py | 2 +- blender-csv-animation | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) create mode 160000 blender-csv-animation diff --git a/.gitmodules b/.gitmodules index 2918b78..01eaa73 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "Drone/FlightLib"] path = Drone/FlightLib url = git://github.com/artem30801/CleverFlightLib.git +[submodule "blender-csv-animation"] + path = blender-csv-animation + url = https://github.com/artem30801/blender-csv-animation diff --git a/Drone/client.py b/Drone/client.py index 19823ff..61004da 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -172,7 +172,6 @@ USE_LEDS = config.getboolean('COPTER', 'use_leds') play_animation.USE_LEDS = USE_LEDS rospy.init_node('Swarm_client', anonymous=True) -print(USE_LEDS) if USE_LEDS: LedLib.init_led() diff --git a/Server/server.py b/Server/server.py index 1764269..9fce4a3 100644 --- a/Server/server.py +++ b/Server/server.py @@ -211,7 +211,7 @@ def send_animations(): #print(ANS) -def send_starttime(dt=30): +def send_starttime(dt=15): timenow = time.time() print('Now:', time.ctime(timenow), "+ dt =", dt) Client.broadcast(Client.form_command("starttime", (str(timenow+dt), ))) diff --git a/blender-csv-animation b/blender-csv-animation new file mode 160000 index 0000000..e494ced --- /dev/null +++ b/blender-csv-animation @@ -0,0 +1 @@ +Subproject commit e494ced31bf045193d9f3ac1c3602fe3ca1db280 From 2dcf51bb0305aeb734fcaa464aad0261cf658a0f Mon Sep 17 00:00:00 2001 From: artem Date: Wed, 13 Feb 2019 20:49:59 +0300 Subject: [PATCH 23/27] Updated submodules --- Drone/FlightLib | 2 +- blender-csv-animation | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Drone/FlightLib b/Drone/FlightLib index ab1b4fc..9993d88 160000 --- a/Drone/FlightLib +++ b/Drone/FlightLib @@ -1 +1 @@ -Subproject commit ab1b4fc08c1654c31d3107a7931697acd01167ec +Subproject commit 9993d88fdcc19f5684fd2db58c8ffa76bb38e34d diff --git a/blender-csv-animation b/blender-csv-animation index e494ced..ef17ebb 160000 --- a/blender-csv-animation +++ b/blender-csv-animation @@ -1 +1 @@ -Subproject commit e494ced31bf045193d9f3ac1c3602fe3ca1db280 +Subproject commit ef17ebbb3493e3fb75538908ca4923a7edb37305 From 7ffc829a1d39ee8908694d7e229c7b55f80fe4c8 Mon Sep 17 00:00:00 2001 From: artem Date: Sat, 16 Feb 2019 11:33:46 +0300 Subject: [PATCH 24/27] Server linux improvements --- .gitignore | 2 ++ Server/server.py | 35 ++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 894a44c..44de96f 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,5 @@ venv.bak/ # mypy .mypy_cache/ +.vscode/settings.json +Server/tests.py diff --git a/Server/server.py b/Server/server.py index 9fce4a3..6f33135 100644 --- a/Server/server.py +++ b/Server/server.py @@ -16,14 +16,19 @@ import configparser # All imports sorted in pyramid +def get_ip_address(): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(("8.8.8.8", 80)) + ip = s.getsockname()[0] + s.close() + return ip + + def auto_connect(): while True: ServerSocket.listen(1) c, addr = ServerSocket.accept() print("Got connection from:", str(addr)) - #client_thread = threading.Thread(target=on_new_client, args=(c, addr)) - #client_thread.start() - if not any(client_addr == addr[0] for client_addr in Client.clients.keys()): client = Client(addr[0]) print("New client") @@ -115,7 +120,7 @@ class Client: self._send_all(msg) else: msg = "ping" - #self._send_all(msg) + # self._send_all(msg) try: # check if data in buffer check = self.socket.recv(BUFFER_SIZE, socket.MSG_PEEK) @@ -206,9 +211,9 @@ def send_animations(): copter.send_file(file, "animation.csv") # TODO config else: print("Filename not matches with any drone connected") - #dr = next(iter(Client.clients.values())) # костыль для тестирования - #ANS = dr.get_response("someshit") - #print(ANS) + # dr = next(iter(Client.clients.values())) # костыль для тестирования + # ANS = dr.get_response("someshit") + # print(ANS) def send_starttime(dt=15): @@ -221,7 +226,7 @@ def send_starttime(dt=15): root = Tk() root.wm_title("Drone swarm operation server") root.style = ttk.Style() -root.style.theme_use("vista") +root.style.theme_use("default") leftFrame = Frame(root) leftFrame.grid(row=0, column=0, padx=10, pady=10) @@ -229,9 +234,9 @@ rightFrame = Frame(root) rightFrame.grid(row=0, column=1, padx=10, pady=10) drone_list = ttkwidgets.CheckboxTreeview(leftFrame, columns=("addr", "connected")) -#drone_list["columns"] = ("addr") -#drone_list.column("name") #width=100 -#drone_list.column("addr") +# drone_list["columns"] = ("addr") +# drone_list.column("name") #width=100 +# drone_list.column("addr") drone_list.heading("#0", text="Drone name") drone_list.heading("#1", text="Connection adress") drone_list.heading("#2", text="Connection status") @@ -264,15 +269,15 @@ NTP_HOST = config['NTP']['host'] NTP_PORT = int(config['NTP']['port']) -ServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socket.socket() # +ServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ServerSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) host = socket.gethostname() -ip = socket.gethostbyname_ex(host)[-1] +ip = get_ip_address() print('Server started on', host, ip, ":", port) -#print('Now:', time.ctime(get_ntp_time(NTP_HOST, NTP_PORT))) +# print('Now:', time.ctime(get_ntp_time(NTP_HOST, NTP_PORT))) print('Waiting for clients...') -ServerSocket.bind((ip[-1], port)) +ServerSocket.bind((ip, port)) autoconnect_thread = threading.Thread(target=auto_connect) autoconnect_thread.daemon = True From 3a229c2e206a97252a2dd282040178be1c9daf22 Mon Sep 17 00:00:00 2001 From: artem30801 <38689676+artem30801@users.noreply.github.com> Date: Sat, 16 Feb 2019 13:21:17 +0300 Subject: [PATCH 25/27] Create README.md --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..6155835 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# CleverSwarm +Програмное обеспечение для запуска шоу дронов под управлением Raspberry Pi с пакетом COEX Clever. +### Пакет включает в себя: +* Аддон для трехмерного редактора Blender, позволяющий экспортировать в формат CSV созданную анимацию движения для одного или нескольких дронов +* Набор ПО для дрона, включащее в себя библиотеку для автономного полёта, модуль для воспроизведения анимаций и клиентское приложение для удаленного синхронизированного управления +* Серверное приложение для удаленного синхронизированного управления дронами и удобной передачи анимации + +## Установка +Скачайте или склонируйте этот репозиторий на компьютер и дроны: +```bash +git clone --recurse-submodules https://github.com/artem30801/CleverSwarm.git +``` +Обновите включенные в пакет подмодули: +```bash +cd CleverSwarm +git submodule foreach git pull origin master +``` From 0441866e0921c2584c2b8b6cb616857f2d9ba928 Mon Sep 17 00:00:00 2001 From: artem30801 <38689676+artem30801@users.noreply.github.com> Date: Sat, 16 Feb 2019 13:23:32 +0300 Subject: [PATCH 26/27] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6155835..64320c6 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,4 @@ git clone --recurse-submodules https://github.com/artem30801/CleverSwarm.git cd CleverSwarm git submodule foreach git pull origin master ``` +Для дальнейших интрукций перейдите на Wiki From 97220cd47eb24c0dff269e35ece79d5161132371 Mon Sep 17 00:00:00 2001 From: artem30801 <38689676+artem30801@users.noreply.github.com> Date: Mon, 18 Feb 2019 00:15:12 +0300 Subject: [PATCH 27/27] Update client.py --- Drone/client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Drone/client.py b/Drone/client.py index 61004da..5f0e56c 100644 --- a/Drone/client.py +++ b/Drone/client.py @@ -101,8 +101,9 @@ def write_to_config(section, option, value): def animation_player(running_event, stop_event): print("Animation thread activated") rate = rospy.Rate(1000 / 100) - first_frame = play_animation.get_frames()[0] - play_animation.takeoff(round(float(first_frame['x']), 4), round(float(first_frame['y']), 4), round(float(first_frame['z']), 4)) + # first_frame = play_animation.get_frames()[0] + # play_animation.takeoff(round(float(first_frame['x']), 4), round(float(first_frame['y']), 4), round(float(first_frame['z']), 4)) + play_animation.takeoff() for current_frame in play_animation.get_frames(): running_event.wait() if stop_event.is_set():