Skip to content

感測器數據視覺化前端開發 #1

Description

@jacky09299

飛機上的感測器會偵測經緯度、溫度、濕度、壓力、高度、俯仰角、傾角、滾轉角,請寫一個視窗,可以顯示出這些值。其中包含一個三維圖,用十字骨架顯示飛機在空中的旋轉滾動(由俯仰角、傾角、滾轉角算出)。還有一個台灣圖,根據經緯度點出飛機的位置。
重要:前端需開發良好,未來若是有增加感測器,可以快速將感測值加入視窗。你可以在後端先自行寫簡單的亂數產生,當作測試。

視窗範例(朝著這個方向努力):
20190516095852393
十字骨架模擬飛機範例(十字架垂直的兩根,一根代表機身,一根代表機翼,不用做到下面圖片中那麼精緻):
請看影片: https://youtu.be/OyEMv5XNU-0?t=945
image_123986672
在台灣圖上點出飛機的位置:
Taiwan_NASA_Terra_MODIS_2022-07-21

參考資料:
俯仰角、傾角、滾轉角: https://ithelp.ithome.com.tw/articles/10226434
pyqt: https://iowiki.com/pyqt/pyqt_index.html
qss: https://steam.oxxostudio.tw/category/python/pyqt5/qss.html
qss: https://zhuanlan.zhihu.com/p/390192953

chatgpt生成範例

import sys
import random
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout,
                             QWidget, QSpinBox, QSplitter, QHBoxLayout, QLabel)
from PyQt5.QtCore import Qt, QTimer
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np


class DynamicMplCanvas(FigureCanvas):
    """一個展示動態三維散點圖的類。"""

    def __init__(self, *args, interval=1000, **kwargs):
        fig = Figure(figsize=(10, 6), dpi=100)
        super().__init__(fig)
        self.axes = fig.add_subplot(111, projection='3d')
        self.timer_event = fig.canvas.new_timer(interval=interval)
        self.timer_event.add_callback(self._update_canvas)
        self.timer_event.start()

    def _update_canvas(self):
        self.axes.clear()
        # 生成隨機數據
        x = np.random.rand(100)
        y = np.random.rand(100)
        z = np.random.rand(100)
        self.axes.scatter(x, y, z)
        self.axes.set_xlabel('X 軸')
        self.axes.set_ylabel('Y 軸')
        self.axes.set_zlabel('Z 軸')
        self.axes.figure.canvas.draw()


class PieChartCanvas(FigureCanvas):
    """用於展示圓餅圖的類。"""

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        super().__init__(fig)
        self.axes = fig.add_subplot(111)
        self.draw_pie_chart()

    def draw_pie_chart(self):
        labels = 'A', 'B', 'C', 'D'
        sizes = [15, 30, 45, 10]
        self.axes.clear()
        self.axes.pie(sizes, labels=labels, autopct='%1.1f%%')
        # Equal aspect ratio ensures that pie is drawn as a circle.
        self.axes.axis('equal')
        self.draw()


class MainWindow(QMainWindow):
    """主視窗類別。"""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWindowTitle("雙動態三維圖表與圓餅圖")
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        # 使用QSplitter進行布局
        self.main_splitter = QSplitter(Qt.Vertical)
        self.top_splitter = QSplitter(Qt.Horizontal)

        # 創建動態圖表並添加到分隔器
        self.dynamic_canvas1 = DynamicMplCanvas(
            self.central_widget, interval=1000)
        self.dynamic_canvas2 = DynamicMplCanvas(
            self.central_widget, interval=1500)
        self.top_splitter.addWidget(self.dynamic_canvas1)
        self.top_splitter.addWidget(self.dynamic_canvas2)

        # 創建圓餅圖和數值框的布局
        bottom_layout = QVBoxLayout()
        self.pie_chart_canvas = PieChartCanvas(self.central_widget)
        bottom_layout.addWidget(self.pie_chart_canvas)

        self.spin_box1 = QSpinBox(self.central_widget)
        self.spin_box2 = QSpinBox(self.central_widget)
        spin_layout = QHBoxLayout()
        spin_layout.addWidget(self.spin_box1)
        spin_layout.addWidget(self.spin_box2)
        bottom_layout.addLayout(spin_layout)

        # 添加溫度顯示框
        self.temperature_label = QLabel("溫度: --°C", self.central_widget)
        self.temperature_label.setAlignment(Qt.AlignCenter)
        self.temperature_label.setStyleSheet("""
            QLabel {
                border: 2px solid #aaaaaa;
                border-radius: 5px;
                padding: 5px;
                background-color: #222222;
                font-size: 14pt;
                color: #eeeeee;
            }
        """)
        bottom_layout.addWidget(self.temperature_label)

        # 設置定時器以定期更新溫度
        self.temperature_timer = QTimer(self)
        self.temperature_timer.timeout.connect(self.update_temperature)
        self.temperature_timer.start(1000)  # 每秒更新一次

        # 將布局放入另一個widget並添加到分隔器
        bottom_widget = QWidget()
        bottom_widget.setLayout(bottom_layout)
        self.main_splitter.addWidget(self.top_splitter)
        self.main_splitter.addWidget(bottom_widget)

        # 設置中央widget的布局
        main_layout = QVBoxLayout(self.central_widget)
        main_layout.addWidget(self.main_splitter)
        self.central_widget.setLayout(main_layout)

        # 添加QSS樣式
        self.setStyleSheet("""
            QMainWindow {
                background-color: #333333;
            }
            QWidget {
                color: #ffffff;
                font-size: 12pt;
                background-color: #444444;
            }
            QSpinBox {
                background-color: #555555;
                border: 1px solid #666666;
                border-radius: 5px;
                padding: 5px;
            }
        """)

    def update_temperature(self):
        # 生成一個隨機溫度值
        temperature = random.uniform(20, 30)
        self.temperature_label.setText(f"溫度: {temperature:.2f}°C")


app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions