Pyqt 实现一套飞行状态监测系统,实时显示SEM等高线图以及飞机当前状态信息

5 篇文章 1 订阅


前言

  通过Pyqt做的一个小软件,主要功能是显示飞行器当前的状态如“机身海拔高度”、“机身坐标”、“偏航角”等,绘制出飞机当前所处区域高程地图。飞机机头朝向随航行方向变化。


效果

  软件效果如下图所示,地图窗口显示地形等高线彩色图,在地图中间位置是飞机,飞机始终位于地图的中心位置,地图随时间位置变化改变显示区域。
  右侧显示飞机各时刻的数据信息,并实时更新。
在这里插入图片描述


核心代码

编程思路

  (1)地图区域的等高线彩色图进行绘制的任务,通过自定义一个派生于QLabel类的MapLabel类实现,重写MapLabel类的paintEvent函数,进行相关的绘图操作,如绘制“圆”、“线段”、“扇形”、“红色飞机”等元素;
  (2)在Widget类中开一个QThread子线程用于实时模拟飞机的运行轨迹,通过time.time()获取系统时间,并利用系统时间激励飞机运行轨迹的更新;
  (3)将QThread子线程中飞机的各个参数与MapLabelMenu(即右侧显示数据的Widget)中的槽函数进行绑定,用QTimer定时更新显示画面;

MapLabel类

  首先需要定义一个Plane类,用于确定地图中间位置的红色小飞机的相关信息。

Plane
+self.icon
+self.location_x = 3000
+self.location_y = 1000
+self.velocity = 0
+self.yaw = 0
+self.altitude = 3000
+self.plane_rotated
+self.transform
+set_location(self, present_point)
+set_yaw(self, yaw)
+set_rotated_plane(self)
+set_velocity(self, velocity)
+set_altitude(self, altitude)

  其中需要定义一个self.plane_rotated用于记录旋转后的飞机的图像。
  成员函数主要用于对该类各属性的赋值操作。

MapLabel
+self.map
+self.northIco #用于存放指北针图像
+self.plane
+self.t = 0
+self.timer
+paintEvent(self, event)

  MapLabel类的属性主要有一个self.map用于存放QImage格式地图数据,self.plane存放Plane对象,self.timer设置了一个定时器用于定时触发QLabel类的update函数,以调用paintEvent函数重绘各种图案。

# 自定义飞机类
class Plane:

    def __init__(self):
        # 当前飞机图像
        self.icon = QImage('./2.png')

        # 飞机当前像素点位置(由经纬度转换过来)、速度、偏航角、高度等信息
        self.location_x = 3000
        self.location_y = 1000
        self.velocity = 0
        self.yaw = 0
        self.altitude = 3000

        # 旋转后的飞机图像
        self.plane_rotated = QImage()

        # 旋转角度(红色飞机根据航向旋转机头朝向)
        self.transform = QTransform()

    def set_location(self, present_point):
        self.location_x = present_point.x()
        self.location_y = present_point.y()

    def set_yaw(self, yaw):
        self.yaw = yaw + 90

    def set_rotated_plane(self):
        self.transform.rotate(self.yaw)
        self.plane_rotated = self.icon.transformed(self.transform)
        self.transform.rotate(-self.yaw)

    def set_velocity(self, velocity):
        self.velocity = velocity

    def set_altitude(self, altitude):
        self.altitude = altitude

# 自定义QLabel类(地图)
class MapLabel(QLabel):

    def __init__(self, parent=None):

        super(MapLabel, self).__init__(parent)

        # 地图、指北针等图片资源
        self.map = QImage('./3.png')
        self.northIco = QImage('./4.png')

        # 创建飞机对象
        self.plane = Plane()

        # 绘图更新
        self.t = 0  # 用于画旋转线段的计数器
        self.timer = QTimer()
        self.timer.timeout.connect(self.update)  # 触发paintEvent
        self.timer.start(10)

    def paintEvent(self, event):

        self.t += 1

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)  # 抗锯齿

        # 将地图的QRect(self.plane.location_x, self.plane.location_y, 600, 600)区域绘制到QLabel的QRect(0, 0, 600, 600)区域中去
        painter.drawImage(QRect(0, 0, 600, 600), self.map,
                          QRect(self.plane.location_x, self.plane.location_y, 600, 600))
        painter.drawImage(QPoint(500, 40), self.northIco)

        # 画圆
        painter.setPen(QPen(QColor(255, 0, 0), 3))  # 后面参数3为线条的粗细
        painter.drawEllipse(QPoint(300, 300), 200, 200)

        # 画线段(旋转线段)
        painter.setPen(QPen(QColor(135, 0, 0), 3))
        painter.drawLine(QPoint(300, 300), QPoint(300 + 200 * math.cos(self.t/100),
                                                  300 + 200 * math.sin(self.t/100)))

        # 画扇形
        painter.setPen(QPen(QColor(255, 135, 2), 3))
        painter.drawPie(QRect(QPoint(50, 50), QPoint(550, 550)), -(self.plane.yaw - 55)*16, 70*16)

        # 设置偏航角及旋转后的飞机图片
        self.plane.set_rotated_plane()
        # 画红色飞机
        painter.drawImage(QPoint(300 - self.plane.plane_rotated.width() / 2,
                                 300 - self.plane.plane_rotated.height() / 2), self.plane.plane_rotated)

PlaneInfo类

  在最外层的Widget类中实现基于时间的激励条件,这里的PlaneInfo类是继承于QThread类,在Widget类中实例化该类后,执行其start()函数,就可以运行run()中的相关操作。

# 运动参数,是关于t的函数,应由外部激励决定,此处为模拟
class PlaneInfo(QThread):
    send_position = pyqtSignal(QPoint)
    send_yaw = pyqtSignal(float)
    send_velocity = pyqtSignal(int)

    def __init__(self):
        super(PlaneInfo, self).__init__()

        self.start_time = time.time()
        self.end_time = 0
        self.during_time = 0
        self.x = 1000
        self.y = 1000
        self.yaw = 0
        self.velocity = 0

    def run(self):

        while True:
            # time.sleep(0.01)
            self.end_time = time.time()
            print(self.end_time)
            print(int(round(self.end_time * 1000)))
            self.during_time = self.end_time - self.start_time
            # x,y关于t的参数方程
            self.x = 100 * self.during_time + 1000
            self.y = 2 * self.during_time * self.during_time + 1000
            self.yaw = math.atan(0.02 * self.during_time) * 1800 / 3.1415926
            # print(self.yaw)
            self.velocity = 4 * self.during_time * self.during_time + 0
            self.send_position.emit(QPoint(self.x, self.y))

            self.send_yaw.emit(float(self.yaw))
            self.send_velocity.emit(int(self.velocity))

资源下载

本案例中涉及到的所有代码、工程文件等,到此处https://download.csdn.net/download/wang_chao118/87031348下载。

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
PyQt5中可以使用多线程来实现状态显示系统时间的功能。以下是一个示例代码: ```python import sys import threading from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel class MainWindow(QMainWindow): def __init__(self): super().__init__() self.statusBar().showMessage("") self.thread = threading.Thread(target=self.update_time) self.thread.daemon = True self.thread.start() self.show() def update_time(self): while True: # 获取当前系统时间 current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 更新状态栏的显示内容 self.statusBar().showMessage("当前时间: " + current_time) time.sleep(1) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() sys.exit(app.exec_()) ``` 在这个示例中,我们创建了一个继承自QMainWindow的窗口类MainWindow。在初始化函数中,我们首先调用了父类的初始化函数,并创建了一个空的状态栏。然后,我们创建了一个新的线程,并通过调用`start()`方法来启动线程。这里我们使用了`threading`模块来创建线程,可以根据自己的需求选择其他方法。 在`update_time`函数中,我们使用一个循环来不断更新状态栏的显示内容。首先,我们通过`datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")`获取当前系统时间,并将其格式化为字符串。然后,我们调用`self.statusBar().showMessage()`方法来更新状态栏的显示内容。最后,我们使用`time.sleep(1)`函数使线程休眠1秒钟,以便每秒更新一次状态栏的时间显示。 在`if __name__ == "__main__":`语句中,我们创建了一个QApplication实例,并将其赋值给`app`变量。然后,我们创建了MainWindow实例,并最后调用`app.exec_()`来启动应用程序的主事件循环。 通过运行这段代码,我们可以在应用程序的状态栏上看到当前系统时间,并且这个显示是以多线程的方式进行更新的。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wang_chao118

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值