最近在做基于公网通信的遥控固定翼。飞机、控制端、服务器都用Python开发。之前没有做过GUI项目,所以搭建了PyQt,尝试发现designer里提供的一些控件都不适用,所以还是需要手写代码。Tkinter之前做过一些相关的练习,所以最终选择了用Tkinter来做控制端的UI。
控制端也跑在树莓派上(因为油门杆、侧杆、AP旋钮什么的用旋转编码器的好接)
使用单屏幕,长宽比约为16:9的样子。整个屏幕分为:
Video 图传的显示
PFD(primary flight display):有姿态仪(飞机上的三轴陀螺仪)、空速表(准备做个皮托管,还没做)、高度表(气压计)、磁航向(电子罗盘)、无线电高度显示(肚子下面放一个TOF传感器)
EWD(Engine and warning display) 显示电涵的转速(来自霍尔传感器)、功率百分比(给电调的PWM的脉宽)、电池电压(电压计)、升降舵 方向舵 副翼(没做flaps)的位置(由于控制端的侧杆、油门杆和舵没做随动设计,autopilot engaged之后机师需要知道这些飞机上器件的位置状态)
一个显示起落架灯的面板 (三个灯)
ND(navigation display):机载的4G模块带GPS 所以有GPS导航 (后期或许为加一个用三轴加速计的惯导玩玩)
ECAM(Airbus的叫法):一个以命令行输出信息和输入指令的地方
个人不喜欢HUD的感觉 所以用numpy+opencv解码收到的数据然后显示在canvas上
大概长这样
在这张图片
中用opencv旋转bank angle度后根据attack angle选定裁取中心的坐标(注意坐标转换)裁取一个正方形 画在canvas上
【还没做 之后补】
from tkinter import *
from time import sleep
from threading import Thread
class rollBar:
def __init__(self, master, width, height, LoR):
self.LoR = LoR
self.frame = Frame(master = master, width = width, height = height, bg = "black")
self.frame.pack()
self.canvas = Canvas(self.frame, width = width, height = height, bg = "grey", bd = 0, highlightthickness = 0)
self.canvas.pack()
self.width = width
self.height = height
self.div_len = height / 4
self.lines = []
self.numbers = []
if LoR == "L":
self.canvas.create_rectangle(10, int(self.height / 2) + 6, self.width - 1, int(self.height / 2) - 6, outline = "white", fill = "black")
elif LoR == "R":
self.canvas.create_rectangle(0, int(self.height / 2) + 6, self.width - 11, int(self.height / 2) - 6, outline = "white", fill = "black")
def turn_on(self, div):
self.div = div
if self.LoR == "L":
self.canvas.create_polygon(10, int(self.height / 2) + 6, 10, int(self.height / 2) - 6, 0, int(self.height / 2), fill = "white")
elif self.LoR == "R":
self.canvas.create_polygon(self.width - 11, int(self.height / 2) + 6, self.width - 11, int(self.height / 2) - 6, self.width - 1, int(self.height / 2), fill = "white")
self.change_to(0)
def change_to(self, val):
# del lines and numbers
for line in self.lines:
self.canvas.delete(line)
self.lines = []
for number in self.numbers:
self.canvas.delete(number)
self.lines = []
# draw lines and numbers
delta_h = (val % self.div) * (self.div_len / self.div)
y = int(self.height / 2 + delta_h)
y_val = val - (val % self.div)
delta_y = 0
delta_y_val = 0
if self.LoR == "L":
while delta_y + y < self.height:
self.lines.append(self.canvas.create_line((0, y + delta_y), (int(self.width / 2), y + delta_y), fill = "white", width = 2))
self.numbers.append(self.canvas.create_text(self.width * 0.75, y + delta_y, text = str(y_val - delta_y_val), fill = "white", font=("Menlo", int(self.width / 5))))
dd_y = 0
while delta_y + y + dd_y < self.height and dd_y < self.div_len:
self.lines.append(self.canvas.create_line((0, y + delta_y + dd_y), (int(self.width / 4), y + delta_y + dd_y), fill = "white", width = 1))
dd_y += int(self.div_len / 5)
delta_y += self.div_len
delta_y_val += self.div
delta_y = 0
# delta_y = self.div_len
delta_y_val = 0
# delta_y_val = self.div
while y - delta_y >= 0:
self.lines.append(self.canvas.create_line((0, y - delta_y), (int(self.width / 2), y - delta_y), fill = "white", width = 2))
self.numbers.append(self.canvas.create_text(int(self.width * 0.75), y - delta_y, text = str(y_val + delta_y_val), fill = "white", font=("Menlo", int(self.width / 5))))
dd_y = 0
while y - delta_y - dd_y >= 0 and dd_y < self.div_len:
self.lines.append(self.canvas.create_line((0, y - delta_y - dd_y), (int(self.width / 4), y - delta_y - dd_y), fill = "white", width = 1))
dd_y += int(self.div_len / 5)
delta_y += self.div_len
delta_y_val += self.div
self.canvas.create_rectangle(10, int(self.height / 2) + 6, self.width - 1, int(self.height / 2) - 6, outline = "white", fill = "black")
self.canvas.create_text(int((self.width - 10) / 2) + 10, int(self.height / 2), text = str(val), fill = "white", font=("Menlo", int(self.width / 5 + 1)))
self.canvas.pack()
elif self.LoR == "R":
while delta_y + y < self.height:
self.lines.append(self.canvas.create_line((self.width - 1, y + delta_y), (int(self.width / 2), y + delta_y), fill = "white", width = 2))
self.numbers.append(self.canvas.create_text(self.width * 0.25, y + delta_y, text = str(y_val - delta_y_val), fill = "white", font=("Menlo", int(self.width / 5))))
dd_y = 0
while delta_y + y + dd_y < self.height and dd_y < self.div_len:
self.lines.append(self.canvas.create_line((self.width - 1, y + delta_y + dd_y), (int(self.width / 4 * 3), y + delta_y + dd_y), fill = "white", width = 1))
dd_y += int(self.div_len / 5)
delta_y += self.div_len
delta_y_val += self.div
delta_y = 0
# delta_y = self.div_len
delta_y_val = 0
# delta_y_val = self.div
while y - delta_y >= 0:
self.lines.append(self.canvas.create_line((self.width - 1, y - delta_y), (int(self.width / 2), y - delta_y), fill = "white", width = 2))
self.numbers.append(self.canvas.create_text(int(self.width * 0.25), y - delta_y, text = str(y_val + delta_y_val), fill = "white", font=("Menlo", int(self.width / 5))))
dd_y = 0
while y - delta_y - dd_y >= 0 and dd_y < self.div_len:
self.lines.append(self.canvas.create_line((self.width - 1, y - delta_y - dd_y), (int(self.width / 4 * 3), y - delta_y - dd_y), fill = "white", width = 1))
dd_y += int(self.div_len / 5)
delta_y += self.div_len
delta_y_val += self.div
self.canvas.create_rectangle(0, int(self.height / 2) + 6, self.width - 11, int(self.height / 2) - 6, outline = "white", fill = "black")
self.canvas.create_text(int((self.width - 10) / 2) + 10, int(self.height / 2), text = str(val), fill = "white", font=("Menlo", int(self.width / 5 + 1)))
self.canvas.pack()
if __name__ == "__main__":
root = Tk()
root.geometry("50x300")
R = rollBar(root, 50, 300, "R")
def c_c():
sleep(1)
R.turn_on(100)
for i in range(500):
R.change_to(i)
sleep(0.01)
t = Thread(target = c_c, args = ())
t.start()
root.mainloop()
from math import sin, cos, pi
from threading import Thread
from time import sleep
from tkinter import *
class Engine:
def __init__(self, master, length, pack_side):
self.length = length
self.frame = Frame(master = master, width = length, height = length, bg = "black")
self.arc = Canvas(self.frame, width = length, height = length, bg = "black", bd = 0, highlightthickness = 0)
self.arc.create_arc(5, 5, length - 5, length - 5, start = 0, extent = 225, style = ARC, outline = "white", width = 2)
self.arc.create_rectangle(0.5 * length, 0.6 * length, 0.9 * length, 0.9 * length, outline = "white", width = 2)
self.arc.pack()
self.frame.pack(side = pack_side, fill = "both")
self.r = length / 2 - 5
self.center = (int(length / 2), int(length / 2))
def turn_on(self, val_min, val_max):
self.val = 0
self.val_max = val_max
self.val_min = val_min
self.text_color = "green"
self.arc.create_text(0.25 * self.length, 0.8 * self.length, text = str(val_min), fill = "white", font=("Menlo", int(self.length / 15)))
self.arc.create_text(0.9 * self.length, 0.55 * self.length, text = str(val_max), fill = "white", font=("Menlo", int(self.length / 15)))
# self.text = self.arc.create_text(0.75 * self.length, 0.8 * self.length, text = str(self.val), fill = self.text_color)
self.text = self.arc.create_text(0.7 * self.length, 0.75 * self.length, text = "", fill = self.text_color, font = ("Menlo", int(self.length / 15)))
self.pointer = self.arc.create_line(self.center, (self._val2pos(0)[0] + self.center[0], self.length - (self._val2pos(0)[1] + self.center[1])), fill = "green", width = 3)
self.arc.pack()
def change_to(self, val):
self.val = val
self.arc.coords(self.pointer, self.center[0], self.center[1], self._val2pos(val)[0] + self.center[0], self.length - (self._val2pos(val)[1] + self.center[1]))
self.arc.itemconfig(self.text, text = str(val))
self.arc.pack()
def _val2pos(self, val):
return (
int(cos((self.val_max - val) / (self.val_max - self.val_min) * (5/4) * pi) * self.r),
int(sin((self.val_max - val) / (self.val_max - self.val_min) * (5/4) * pi) * self.r)
)
if __name__ == "__main__":
print(__name__)
root = Tk()
root.geometry("800x400")
root.configure(bg = "black")
E_1 = Engine(root, 400, "left")
E_2 = Engine(root, 400, "right")
def turn_on():
sleep(5)
E_1.turn_on(0, 100)
for i in range(0, 101):
E_1.change_to(i)
sleep(0.01)
t = Thread(target = turn_on, args = ())
t.start()
root.mainloop()