diff --git a/src/GUI/gui.py b/src/GUI/gui.py index 2803f50..3ec9c3c 100644 --- a/src/GUI/gui.py +++ b/src/GUI/gui.py @@ -32,7 +32,7 @@ from mission_group import ( # ================================================================================ class ControlStationUI(QMainWindow): - VERSION = '2.0.0' + VERSION = '2.0.1' def __init__(self): super().__init__() @@ -43,8 +43,7 @@ class ControlStationUI(QMainWindow): import queue self.message_queue = queue.Queue() - # 初始化ROS2 - rclpy.init() + # 初始化ROS2 Monitor(ROS2 本身在 main() 中已初始化) self.monitor = DroneMonitor() self.monitor.signals.update_signal.connect(self.update_ui) @@ -1723,8 +1722,42 @@ class ControlStationUI(QMainWindow): event.accept() +def main(): + """ + GUI 應用程式的主入口點 + + 標準 ROS2 + Qt 架構: + 1. 在最外層/最前面只做一次 rclpy.init() + 2. 啟動 Qt 應用程式 + 3. 在 finally 中做 rclpy.shutdown() + + 這樣可以確保所有 ROS2 相關操作都共享同一個初始化狀態 + """ + # 第一步:在最外層只初始化一次 ROS2 + print("🚀 [GUI] 初始化 ROS2...", flush=True) + rclpy.init() + print("✓ [GUI] ROS2 初始化完成", flush=True) + + try: + # 第二步:啟動 Qt 應用程式 + print("🚀 [GUI] 啟動 Qt 應用程式...", flush=True) + app = QApplication(sys.argv) + station = ControlStationUI() + station.show() + print("✓ [GUI] 應用程式已啟動", flush=True) + + # 第三步:進入 Qt 事件循環(阻塞直到用戶關閉應用) + print("🎯 [GUI] 進入主事件循環,等待用戶操作...", flush=True) + sys.exit(app.exec()) + + finally: + # 第四步:只有當 GUI 視窗被關閉時,才做 ROS2 cleanup + print("\n🛑 [GUI] 應用程式關閉,正在清理 ROS2 資源...", flush=True) + if rclpy.ok(): + rclpy.shutdown() + print("✓ [GUI] ROS2 已關閉", flush=True) + print("✓ [GUI] 應用程式完全退出", flush=True) + + if __name__ == '__main__': - app = QApplication(sys.argv) - station = ControlStationUI() - station.show() - app.exec() \ No newline at end of file + main() \ No newline at end of file