feat: 新增任務規劃系統 (M-Formation, Circle, Leader-Follower, Grid Sweep)
- mission_planner: 四種任務模式,Leader-Follower 支援 Bezier 曲線轉彎 - mission_executor: QTimer 驅動的多航點執行器 - command_sender: MAVLink setpoint 發送抽象層 - gui: 地圖任務模式選單 + 框選/路徑標記觸發 - map_layout: 任務模式下拉選單 + 確認路徑按鈕 + route bridge 信號 - verify_waypoints: 靜態航點圖 + 動畫模擬驗證 (Play/Pause/Reset)
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
指令發送模組
|
||||
負責將目標位置轉成具體的通訊指令發送到飛控
|
||||
|
||||
現階段: MavlinkSender (直接 pymavlink 發送)
|
||||
未來: 替換為 ROS2Sender (發到 ROS2 topic,由 fc_network_adapter 轉發)
|
||||
"""
|
||||
from abc import ABC, abstractmethod
|
||||
from pymavlink import mavutil
|
||||
|
||||
|
||||
class CommandSender(ABC):
|
||||
"""指令發送抽象介面"""
|
||||
|
||||
@abstractmethod
|
||||
def send_position_global(self, sysid, lat, lon, alt):
|
||||
"""
|
||||
發送全球座標位置指令
|
||||
|
||||
Args:
|
||||
sysid: 目標無人機的 MAVLink system ID
|
||||
lat: 緯度 (度)
|
||||
lon: 經度 (度)
|
||||
alt: 高度 (公尺)
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def close(self):
|
||||
"""關閉連線"""
|
||||
pass
|
||||
|
||||
|
||||
class MavlinkSender(CommandSender):
|
||||
"""
|
||||
MAVLink 直接發送 (驗證階段用)
|
||||
透過 SET_POSITION_TARGET_GLOBAL_INT 發送目標位置
|
||||
|
||||
使用方式:
|
||||
sender = MavlinkSender("udpout:127.0.0.1:14550")
|
||||
sender.send_position_global(sysid=1, lat=24.123, lon=120.567, alt=10.0)
|
||||
"""
|
||||
|
||||
# type_mask: 只使用位置 (lat, lon, alt)
|
||||
# 忽略速度 (bit 3,4,5)、加速度 (bit 6,7,8)、yaw (bit 10)、yaw_rate (bit 11)
|
||||
TYPE_MASK_POSITION_ONLY = (
|
||||
0b0000_1101_1111_1000 # = 0x0DF8
|
||||
)
|
||||
|
||||
def __init__(self, connection_string="udpout:127.0.0.1:14550"):
|
||||
"""
|
||||
Args:
|
||||
connection_string: MAVLink 連線字串
|
||||
SITL 範例: "udpout:127.0.0.1:14550"
|
||||
"""
|
||||
self.connection_string = connection_string
|
||||
self.mav = mavutil.mavlink_connection(connection_string)
|
||||
print(f"MavlinkSender 已建立連線: {connection_string}")
|
||||
|
||||
def send_position_global(self, sysid, lat, lon, alt):
|
||||
"""
|
||||
發送 SET_POSITION_TARGET_GLOBAL_INT
|
||||
|
||||
注意:
|
||||
- coordinate_frame 使用 MAV_FRAME_GLOBAL_RELATIVE_ALT_INT
|
||||
高度是相對起飛點的高度 (公尺)
|
||||
- 如果 FormationPlanner 產出的 alt 是 AMSL 絕對高度,
|
||||
需要在外部先減去起飛點高度再傳入
|
||||
"""
|
||||
self.mav.mav.set_position_target_global_int_send(
|
||||
0, # time_boot_ms (不使用)
|
||||
sysid, # target_system
|
||||
1, # target_component (autopilot)
|
||||
mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT_INT,
|
||||
self.TYPE_MASK_POSITION_ONLY,
|
||||
int(lat * 1e7), # lat_int
|
||||
int(lon * 1e7), # lon_int
|
||||
float(alt), # alt
|
||||
0, 0, 0, # vx, vy, vz (忽略)
|
||||
0, 0, 0, # afx, afy, afz (忽略)
|
||||
0, 0 # yaw, yaw_rate (忽略)
|
||||
)
|
||||
|
||||
def close(self):
|
||||
"""關閉 MAVLink 連線"""
|
||||
if self.mav:
|
||||
self.mav.close()
|
||||
self.mav = None
|
||||
print("MavlinkSender 已關閉")
|
||||
Reference in New Issue
Block a user