|
|
|
|
@ -12,6 +12,7 @@ import asyncio
|
|
|
|
|
import json
|
|
|
|
|
import subprocess
|
|
|
|
|
import time
|
|
|
|
|
import traceback
|
|
|
|
|
|
|
|
|
|
# 導入分離的類別
|
|
|
|
|
from communication import DroneMonitor, UDPMavlinkReceiver, WebSocketMavlinkReceiver
|
|
|
|
|
@ -379,6 +380,8 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
status_label.setToolTip("運行中")
|
|
|
|
|
self.statusBar().showMessage(f"已啟動 Serial 連接: {conn['port']}", 3000)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ Serial 連接啟動失敗: {str(e)}")
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
self.statusBar().showMessage(f"啟動 Serial 連接失敗: {str(e)}", 5000)
|
|
|
|
|
|
|
|
|
|
def remove_serial_connection(self, conn, panel):
|
|
|
|
|
@ -496,7 +499,6 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
print(f"⚠️ {action} 被取消")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ {action} 錯誤: {str(e)}")
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
self.statusBar().showMessage(f"{action} 錯誤: {str(e)}", 3000)
|
|
|
|
|
|
|
|
|
|
@ -798,12 +800,12 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
except Exception as service_error:
|
|
|
|
|
msg = f"❌ {drone_id} 服務調用錯誤: {str(service_error)}"
|
|
|
|
|
print(f" {msg}", flush=True)
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
self.message_queue.put((msg, 2000))
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
msg = f"❌ {drone_id} 錯誤: {str(e)}"
|
|
|
|
|
print(f" {msg}", flush=True)
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
self.message_queue.put((msg, 2000))
|
|
|
|
|
self.message_queue.put((msg, 2000))
|
|
|
|
|
@ -1229,7 +1231,6 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.statusBar().showMessage(f"❌ Group {group.group_id}: 規劃失敗: {str(e)}", 5000)
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
# ================================================================================
|
|
|
|
|
@ -1301,7 +1302,6 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.statusBar().showMessage(f"❌ Group {group.group_id}: Grid Sweep 規劃失敗: {str(e)}", 5000)
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
# ================================================================================
|
|
|
|
|
@ -1381,7 +1381,6 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.statusBar().showMessage(f"❌ Group {group.group_id}: 跟隨模式規劃失敗: {str(e)}", 5000)
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
# ================================================================================
|
|
|
|
|
@ -1663,6 +1662,7 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
break
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ 消息隊列處理錯誤: {e}", flush=True)
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
def _spin_asyncio(self):
|
|
|
|
|
"""驅動 asyncio 事件循環,允許異步任務執行
|
|
|
|
|
@ -1678,7 +1678,8 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
loop.run_until_complete(asyncio.sleep(0))
|
|
|
|
|
except Exception as e:
|
|
|
|
|
# 靜默忽略任何錯誤,防止 Qt 定時器出現異常
|
|
|
|
|
pass
|
|
|
|
|
# 但仍然打印詳細的堆棧跟踪以便調試
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
def spin_ros(self):
|
|
|
|
|
try:
|
|
|
|
|
@ -1694,8 +1695,10 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
print(f"⚠️ ROS2 context 錯誤(忽略): {e}", flush=True)
|
|
|
|
|
else:
|
|
|
|
|
print(f"ROS spin error: {e}", flush=True)
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"ROS spin error: {e}", flush=True)
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
def closeEvent(self, event):
|
|
|
|
|
try:
|
|
|
|
|
@ -1711,6 +1714,7 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
self.executor.shutdown()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"⚠️ 清理資源時出錯: {e}", flush=True)
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
# 安全地 shutdown ROS2
|
|
|
|
|
try:
|
|
|
|
|
@ -1718,6 +1722,7 @@ class ControlStationUI(QMainWindow):
|
|
|
|
|
rclpy.shutdown()
|
|
|
|
|
except RuntimeError as e:
|
|
|
|
|
print(f"⚠️ ROS2 shutdown 錯誤: {e}", flush=True)
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
event.accept()
|
|
|
|
|
|
|
|
|
|
|