2026.8.7全代码限速
This commit is contained in:
@@ -2,9 +2,17 @@
|
|||||||
mission_manager.py — 基于 ZeroMQ RouterProxy 的航点巡航状态机
|
mission_manager.py — 基于 ZeroMQ RouterProxy 的航点巡航状态机
|
||||||
|
|
||||||
【协议变更 v2 — 2026-07】
|
【协议变更 v2 — 2026-07】
|
||||||
航点存储格式使用经纬度 (lat, lon, alt)。发送 POSITION SETPOINT
|
航点存储格式使用经纬度 (lat, lon, alt)。导航/返航/悬停均发送
|
||||||
时在本模块内转换为相对当前位置的 LOCAL_OFFSET_NED 偏移
|
VELOCITY SETPOINT:把目标经纬度换算成相对当前位置的 NED 方向,
|
||||||
(x=北向, y=东向, z=向下)。
|
再按 max_speed 限速成速度命令(差分量,与参考原点无关)。
|
||||||
|
|
||||||
|
【坐标系说明 — 2026-08 修复】
|
||||||
|
此前 POSITION LOCAL_OFFSET_NED 路径用 GPS 经纬度反算相对偏移,
|
||||||
|
交给 PX4 在自身 LOCAL_NED 帧解析。GPS 与本地估计一旦不一致
|
||||||
|
(跳变/漂移),目标跟着跳、飞控满速追(实测 HOLD_FINAL 7.77m/s)。
|
||||||
|
故 HOLD_TASK / HOLD_FINAL 悬停改为速度闭环,从根上消除
|
||||||
|
GPS↔本地帧混用。POSITION setpoint 仅保留给 TAKEOFF 预热/降级爬升
|
||||||
|
(零水平偏移,且已加单帧钳制)。
|
||||||
|
|
||||||
【核心改动】
|
【核心改动】
|
||||||
1. self.drone → self.proxy(注入的 RouterProxy 实例)
|
1. self.drone → self.proxy(注入的 RouterProxy 实例)
|
||||||
@@ -670,12 +678,14 @@ class MissionManager:
|
|||||||
self.tracking_completed = False
|
self.tracking_completed = False
|
||||||
return
|
return
|
||||||
|
|
||||||
# ---- 保持当前位置悬停(相对当前位置 LOCAL_OFFSET_NED) ----
|
# ---- 保持当前位置悬停(速度闭环,坐标系一致) ----
|
||||||
|
# 说明:悬停不用 POSITION LOCAL_OFFSET_NED。位置模式把"由 GPS 经纬度
|
||||||
|
# 反算的相对偏移"交给 PX4 在自身 LOCAL_NED 帧里解析,GPS 与本地估计
|
||||||
|
# 一旦不一致(跳变/漂移),目标跟着跳、飞控满速追(曾实测 7.77m/s)。
|
||||||
|
# 速度模式是差分量,与参考原点无关,命令值即速度上界,天然安全。
|
||||||
wp = self.waypoints[self.current_wp_index]
|
wp = self.waypoints[self.current_wp_index]
|
||||||
self._send_relative_position_setpoint(
|
self._send_velocity_to_target(
|
||||||
state,
|
state, wp["lat"], wp["lon"], wp.get("alt", self.target_altitude),
|
||||||
wp["lat"], wp["lon"], wp.get("alt", self.target_altitude),
|
|
||||||
yaw=wp.get("yaw", 0),
|
|
||||||
)
|
)
|
||||||
self.current_target = {
|
self.current_target = {
|
||||||
"lat": wp["lat"], "lon": wp["lon"],
|
"lat": wp["lat"], "lon": wp["lon"],
|
||||||
@@ -857,7 +867,8 @@ class MissionManager:
|
|||||||
"""
|
"""
|
||||||
[HOLD_FINAL] 末端悬停,保持最终航点位置
|
[HOLD_FINAL] 末端悬停,保持最终航点位置
|
||||||
|
|
||||||
POSITION SETPOINT 发送 LOCAL_OFFSET_NED 相对偏移。
|
使用速度闭环(_send_velocity_to_target)而非 POSITION LOCAL_OFFSET_NED,
|
||||||
|
避免 GPS 偏移与 PX4 本地坐标系不一致导致飞控满速追目标(曾实测 7.77m/s)。
|
||||||
"""
|
"""
|
||||||
if self.waypoints:
|
if self.waypoints:
|
||||||
final_wp = self.waypoints[-1]
|
final_wp = self.waypoints[-1]
|
||||||
@@ -865,11 +876,10 @@ class MissionManager:
|
|||||||
final_wp = {"lat": 0.0, "lon": 0.0,
|
final_wp = {"lat": 0.0, "lon": 0.0,
|
||||||
"alt": self.target_altitude, "yaw": 0}
|
"alt": self.target_altitude, "yaw": 0}
|
||||||
|
|
||||||
self._send_relative_position_setpoint(
|
self._send_velocity_to_target(
|
||||||
state,
|
state,
|
||||||
final_wp["lat"], final_wp["lon"],
|
final_wp["lat"], final_wp["lon"],
|
||||||
final_wp.get("alt", self.target_altitude),
|
final_wp.get("alt", self.target_altitude),
|
||||||
yaw=final_wp.get("yaw", 0),
|
|
||||||
)
|
)
|
||||||
self.current_target = {
|
self.current_target = {
|
||||||
"lat": final_wp["lat"], "lon": final_wp["lon"],
|
"lat": final_wp["lat"], "lon": final_wp["lon"],
|
||||||
@@ -886,8 +896,23 @@ class MissionManager:
|
|||||||
# ================================================================
|
# ================================================================
|
||||||
|
|
||||||
def _send_relative_position_setpoint(self, state, target_lat, target_lon,
|
def _send_relative_position_setpoint(self, state, target_lat, target_lon,
|
||||||
target_alt, yaw=0.0):
|
target_alt, yaw=0.0, max_speed=None):
|
||||||
"""按相对当前位置的 LOCAL_OFFSET_NED 发送 POSITION SETPOINT。"""
|
"""
|
||||||
|
按相对当前位置的 LOCAL_OFFSET_NED 发送 POSITION SETPOINT。
|
||||||
|
|
||||||
|
统一限速:位置设定点按单帧最大推进距离 max_step 钳制,
|
||||||
|
即大偏移被拆成多帧逐步逼近,从源头避免飞控满速冲撞。
|
||||||
|
(此前 HOLD_FINAL 阶段曾因偏移异常出现 7.77m/s 失控)
|
||||||
|
|
||||||
|
max_step = max(max_speed * 0.5, 0.3)。正常悬停(偏移 < 0.3m)
|
||||||
|
不受影响;异常大偏移被钳制的同时打印 WARNING 便于诊断。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
max_speed: 限速(m/s),默认 self.max_speed
|
||||||
|
"""
|
||||||
|
if max_speed is None:
|
||||||
|
max_speed = self.max_speed
|
||||||
|
|
||||||
drone = state.get("drone", {}) if state else {}
|
drone = state.get("drone", {}) if state else {}
|
||||||
current_lat = drone.get("lat", 0.0)
|
current_lat = drone.get("lat", 0.0)
|
||||||
current_lon = drone.get("lon", 0.0)
|
current_lon = drone.get("lon", 0.0)
|
||||||
@@ -898,6 +923,19 @@ class MissionManager:
|
|||||||
current_lat, current_lon, current_alt,
|
current_lat, current_lon, current_alt,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ---- 统一限速:单帧最大目标偏移(约半个限速秒距离) ----
|
||||||
|
max_step = max(max_speed * 0.5, 0.3)
|
||||||
|
dist_h = math.sqrt(x * x + y * y)
|
||||||
|
if dist_h > max_step * 1.5:
|
||||||
|
logger.warning(
|
||||||
|
"[限速] POSITION 偏移过大 %.1fm,钳制为 %.1fm(max_speed=%.1f)",
|
||||||
|
dist_h, max_step, max_speed)
|
||||||
|
if dist_h > max_step:
|
||||||
|
x = x / dist_h * max_step
|
||||||
|
y = y / dist_h * max_step
|
||||||
|
# 垂直方向同样钳制(z>0 表示目标在下)
|
||||||
|
z = max(min(z, max_step), -max_step)
|
||||||
|
|
||||||
return self.proxy.send_setpoint(
|
return self.proxy.send_setpoint(
|
||||||
x=x, y=y, z=z, yaw=yaw,
|
x=x, y=y, z=z, yaw=yaw,
|
||||||
frame="LOCAL_OFFSET_NED",
|
frame="LOCAL_OFFSET_NED",
|
||||||
|
|||||||
+4
-3
@@ -13,7 +13,7 @@ run_mission.py — 基于 ZMQ Router 协议的主任务入口
|
|||||||
▼ ▼
|
▼ ▼
|
||||||
┌─ MissionManager ┌─ UAVControlLoop ──┐
|
┌─ MissionManager ┌─ UAVControlLoop ──┐
|
||||||
│ 状态机 + 航点巡航 │ 20Hz VELOCITY │
|
│ 状态机 + 航点巡航 │ 20Hz VELOCITY │
|
||||||
│ POSITION SETPOINT │ 闭环追踪 │
|
│ VELOCITY SETPOINT │ 闭环追踪 │
|
||||||
│ (非追踪期间) │ (VISUAL_TRACKING) │
|
│ (非追踪期间) │ (VISUAL_TRACKING) │
|
||||||
└───────────────────┴────────────────────┘
|
└───────────────────┴────────────────────┘
|
||||||
┌─ 感知模块 ─────────┐
|
┌─ 感知模块 ─────────┐
|
||||||
@@ -23,7 +23,8 @@ run_mission.py — 基于 ZMQ Router 协议的主任务入口
|
|||||||
|
|
||||||
【控制权协调规则】
|
【控制权协调规则】
|
||||||
同一时刻只有一个人持有「SETPOINT 发令权」:
|
同一时刻只有一个人持有「SETPOINT 发令权」:
|
||||||
- VISUAL_TRACKING 之外 → MissionManager 发 POSITION SETPOINT
|
- VISUAL_TRACKING 之外 → MissionManager 发 VELOCITY SETPOINT(航点/
|
||||||
|
悬停均用速度闭环,与坐标系无关;仅 TAKEOFF 预热用零偏移 POSITION)
|
||||||
- VISUAL_TRACKING 之中 → UAVControlLoop 线程发 VELOCITY SETPOINT
|
- VISUAL_TRACKING 之中 → UAVControlLoop 线程发 VELOCITY SETPOINT
|
||||||
- 切换由主循环检测 MissionManager.state 变化时触发
|
- 切换由主循环检测 MissionManager.state 变化时触发
|
||||||
|
|
||||||
@@ -479,7 +480,7 @@ class MissionOrchestrator:
|
|||||||
┌──────────────┬─────────────────────┬──────────────────────┐
|
┌──────────────┬─────────────────────┬──────────────────────┐
|
||||||
│ 状态机状态 │ MissionManager │ UAVControlLoop │
|
│ 状态机状态 │ MissionManager │ UAVControlLoop │
|
||||||
├──────────────┼─────────────────────┼──────────────────────┤
|
├──────────────┼─────────────────────┼──────────────────────┤
|
||||||
│ 非 TRACKING │ proxy → POSITION │ 控制线程已停止 │
|
│ 非 TRACKING │ proxy → VELOCITY │ 控制线程已停止 │
|
||||||
│ │ SETPOINT │ │
|
│ │ SETPOINT │ │
|
||||||
├──────────────┼─────────────────────┼──────────────────────┤
|
├──────────────┼─────────────────────┼──────────────────────┤
|
||||||
│ TRACKING │ 不发 SETPOINT │ 20Hz VELOCITY 线程 │
|
│ TRACKING │ 不发 SETPOINT │ 20Hz VELOCITY 线程 │
|
||||||
|
|||||||
Reference in New Issue
Block a user