base_agent/uas/uas_control/main.py

344 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import sys
from PyQt5.QtWidgets import QApplication
from uas.uas_control.base_controller import BaseUASController
from uas.uas_control.command import CommandType, Commands
from uas.uas_control.controllers.robot_dog_controller import SEP, RobotDogController
from uas.uas_control.controllers.uav_controller import UAVController
from uas.uas_control.controllers.usv_controller import USVController
from uas.uas_control.manager import UASManager
from uas.uas_control.protocols.mavlink_adapter import MAVLinkAdapter
from uas.uas_control.protocols.ros_adapter import ROSAdapter
from uas.uas_control.protocols.simulation_adapter import SimulationAdapter
# ═════════════════════════════════════════════════════════════════
# 演示函数
# ═════════════════════════════════════════════════════════════════
def demo_uav_mavlink(app: QApplication):
print(f"\n{SEP}\n 演示1无人机 × MAVLink 适配器\n{SEP}")
adapter = MAVLinkAdapter(
device_id = "UAV-001",
connection_string = "udp:127.0.0.1:14550",
)
uav = UAVController("UAV-001", adapter)
results, errors = [], []
uav.command_result.connect(lambda r: results.append(r))
uav.error_occurred.connect(lambda m: errors.append(m))
assert uav.connect(), "连接应成功"
print(f" 连接状态 : {uav.is_connected}")
print(f" 适配器 : {adapter}")
# 标准起飞流程
flow = [
("解锁", uav.arm()),
("起飞50m", uav.takeoff(altitude=50.0, speed=3.0)),
("前往目标", uav.goto(39.95, 116.45, 100.0, speed=10.0)),
("云台俯仰", uav.set_gimbal(pitch=-45.0)),
("拍照", uav.camera_shoot()),
("录像开始", uav.camera_record(start=True)),
("盘旋", uav.loiter(radius=80.0)),
("录像停止", uav.camera_record(start=False)),
("返航", uav.rtl()),
("降落", uav.land()),
("加锁", uav.disarm()),
]
for name, result in flow:
mark = "" if result.success else ""
print(f" {mark} {name:8s}: {result.message[:45]}")
# 遥测
app.processEvents()
telem = uav.get_telemetry()
if telem:
print(f"\n 遥测快照 : {telem}")
print(f" 指令历史 : {len(uav.command_history)}")
uav.disconnect()
print(f" ✅ MAVLink 适配器演示通过\n")
def demo_robot_dog_ros(app: QApplication):
print(f"\n{SEP}\n 演示2机器狗 × ROS2 适配器\n{SEP}")
adapter = ROSAdapter(
device_id = "DOG-001",
ros_version = 2,
namespace = "spot",
device_type = "robot_dog",
)
dog = RobotDogController("DOG-001", adapter)
results = []
dog.command_result.connect(lambda r: results.append(r))
dog.connect()
print(f" 连接状态 : {dog.is_connected}")
print(f" 适配器 : {adapter}")
# 机器狗动作序列
actions = [
("站立", dog.stand()),
("设置高度", dog.set_body_height(0.6)),
("行走", dog.walk(speed=1.5, heading=90.0)),
("小跑", dog.trot(speed=2.5)),
("设置步态", dog.set_gait("TROT")),
("爬楼梯", dog.climb_stairs()),
("自定义", dog.custom_command("led_blink", color="red", hz=2)),
("坐下", dog.sit()),
]
for name, result in actions:
mark = "" if result.success else ""
print(f" {mark} {name:8s}: {result.message[:45]}")
app.processEvents()
telem = dog.get_telemetry()
if telem:
print(f"\n 遥测快照 : {telem}")
dog.disconnect()
print(f" ✅ ROS2 适配器演示通过\n")
def demo_protocol_hotswap(app: QApplication):
print(f"\n{SEP}\n 演示3协议热切换MAVLink → ROS2\n{SEP}")
# 初始使用 MAVLink
mav_adapter = MAVLinkAdapter("UAV-002", "udp:127.0.0.1:14551")
uav = UAVController("UAV-002", mav_adapter)
uav.connect()
r1 = uav.arm()
print(f" MAVLink 解锁: {'' if r1.success else ''} {r1.message[:40]}")
print(f" 当前适配器 : {uav._adapter.__class__.__name__}")
# 热切换到 ROS2
ros_adapter = ROSAdapter(
"UAV-002", ros_version=2,
namespace="uav2", device_type="controller"
)
uav.switch_adapter(ros_adapter)
uav.connect()
r2 = uav.goto(39.9, 116.4, 80.0)
print(f" ROS2 GOTO : {'' if r2.success else ''} {r2.message[:40]}")
print(f" 切换后适配器: {uav._adapter.__class__.__name__}")
# 再切换回仿真适配器
sim_adapter = SimulationAdapter("UAV-002", device_type="controller")
uav.switch_adapter(sim_adapter)
uav.connect()
r3 = uav.takeoff(100.0)
print(f" 仿真 起飞 : {'' if r3.success else ''} {r3.message[:40]}")
print(f" 最终适配器 : {uav._adapter.__class__.__name__}")
uav.disconnect()
print(f" ✅ 协议热切换演示通过\n")
def demo_multi_device_manager(app: QApplication):
print(f"\n{SEP}\n 演示4多设备统一管理UASManager\n{SEP}")
manager = UASManager()
alerts = []
manager.alert.connect(lambda did, msg: alerts.append(f"[{did}] {msg}"))
# 注册 3 架无人机 + 2 只机器狗 + 1 艘无人船
devices = [
UAVController("UAV-A",
SimulationAdapter("UAV-A", device_type="controller")),
UAVController("UAV-B",
SimulationAdapter("UAV-B", device_type="controller")),
UAVController("UAV-C",
MAVLinkAdapter("UAV-C", "udp:127.0.0.1:14552")),
RobotDogController("DOG-A",
SimulationAdapter("DOG-A", device_type="robot_dog")),
RobotDogController("DOG-B",
ROSAdapter("DOG-B", ros_version=2,
namespace="dog_b", device_type="robot_dog")),
USVController("USV-A",
SimulationAdapter("USV-A", device_type="controller")),
]
for d in devices:
manager.register(d)
print(f" 已注册设备: {manager.device_count}")
# 批量连接
conn_results = manager.connect_all()
ok_count = sum(1 for v in conn_results.values() if v)
print(f" 批量连接 : {ok_count}/{len(conn_results)} 成功")
# 广播:所有无人机解锁
print(f"\n 广播:所有无人机解锁")
arm_results = manager.broadcast(
lambda did: Commands.arm(did), device_type="controller"
)
for did, r in arm_results.items():
print(f" {'' if r.success else ''} {did}: {r.message[:35]}")
# 广播:所有机器狗站立
print(f"\n 广播:所有机器狗站立")
stand_results = manager.broadcast(
lambda did: Commands.stand(did), device_type="robot_dog"
)
for did, r in stand_results.items():
print(f" {'' if r.success else ''} {did}: {r.message[:35]}")
# 单独控制
print(f"\n 单独控制 UAV-A 起飞")
uav_a: UAVController = manager.get("UAV-A")
r = uav_a.takeoff(altitude=80.0)
print(f" {'' if r.success else ''} UAV-A 起飞: {r.message[:40]}")
print(f"\n 单独控制 DOG-A 行走")
dog_a: RobotDogController = manager.get("DOG-A")
r = dog_a.walk(speed=2.0, heading=45.0)
print(f" {'' if r.success else ''} DOG-A 行走: {r.message[:40]}")
# 遥测快照
app.processEvents()
print(f"\n 遥测快照(所有设备):")
for did, telem in manager.get_all_telemetry().items():
if telem:
print(f" {did:8s} bat={telem.battery_percent:3d}% "
f"spd={telem.ground_speed:.1f}m/s "
f"pos=({telem.latitude:.4f},{telem.longitude:.4f})")
# 协议热切换(通过 Manager
print(f"\n UAV-A 协议热切换: Simulation → MAVLink")
new_adapter = MAVLinkAdapter("UAV-A", "udp:127.0.0.1:14553")
manager.switch_protocol("UAV-A", new_adapter)
r = uav_a.goto(39.95, 116.45, 100.0)
print(f" {'' if r.success else ''} UAV-A GOTO (MAVLink): "
f"{r.message[:35]}")
# 紧急停止所有
print(f"\n 触发:紧急停止所有设备")
stop_results = manager.emergency_stop_all()
ok = sum(1 for r in stop_results.values() if r.success)
print(f" 紧急停止: {ok}/{len(stop_results)} 成功")
# 状态报告
print(f"\n{manager.status_report()}")
manager.disconnect_all()
print(f" ✅ 多设备管理演示通过\n")
def demo_fault_injection(app: QApplication):
print(f"\n{SEP}\n 演示5故障注入与容错\n{SEP}")
adapter = SimulationAdapter(
"UAV-FAULT", device_type="controller",
fail_rate=0.0, latency_ms=10.0
)
uav = UAVController("UAV-FAULT", adapter)
uav.connect()
errors = []
uav.error_occurred.connect(lambda m: errors.append(m))
# 正常发送
r = uav.arm()
print(f" 正常模式 ARM: {'' if r.success else ''} {r.message[:40]}")
# 注入 80% 故障率
adapter.inject_fault(0.8)
print(f"\n 注入故障率 80%,连续发送 10 条指令:")
success_cnt = 0
for i in range(10):
r = uav.goto(39.9 + i*0.001, 116.4, 50.0)
if r.success:
success_cnt += 1
print(f" [{i+1:02d}] {'' if r.success else ''} "
f"{r.message[:40]}")
print(f"\n 成功率: {success_cnt}/10 "
f"(期望约 2/10实际随机")
# 恢复正常
adapter.inject_fault(0.0)
r = uav.emergency_stop()
print(f"\n 恢复后 EMERGENCY_STOP: "
f"{'' if r.success else ''} {r.message[:40]}")
# 回调注册
cb_results = []
uav.register_callback(
CommandType.GOTO,
lambda r: cb_results.append(r)
)
uav.goto(39.9, 116.4, 50.0)
print(f"\n 指令回调触发: {len(cb_results)}")
assert len(cb_results) == 1
uav.disconnect()
print(f" ✅ 故障注入演示通过\n")
def demo_custom_extension(app: QApplication):
print(f"\n{SEP}\n 演示6自定义扩展无人船 USV\n{SEP}")
# USVController 继承 BaseUASController
# 复用 SimulationAdapter无需修改任何底层代码
adapter = SimulationAdapter("USV-001", device_type="controller")
usv = USVController("USV-001", adapter)
usv.connect()
actions = [
("差速推进", usv.set_throttle(left=0.8, right=0.6)),
("前往目标", usv.goto(22.5, 113.9, 0.0, speed=5.0)),
("水面巡逻", usv.patrol([
(22.50, 113.90, 0.0, 5.0),
(22.52, 113.92, 0.0, 5.0),
(22.54, 113.90, 0.0, 5.0),
])),
("抛锚", usv.anchor()),
("紧急停止", usv.emergency_stop()),
]
for name, result in actions:
mark = "" if result.success else ""
print(f" {mark} {name:8s}: {result.message[:45]}")
print(f"\n USVController 继承关系验证:")
print(f" isinstance(usv, BaseUASController) = "
f"{isinstance(usv, BaseUASController)}")
print(f" device_type = {usv.device_type}")
print(f" adapter = {usv._adapter.__class__.__name__}")
usv.disconnect()
print(f" ✅ 自定义扩展演示通过\n")
# ═════════════════════════════════════════════════════════════════
# 主入口
# ═════════════════════════════════════════════════════════════════
def main():
app = QApplication(sys.argv)
demo_uav_mavlink(app)
demo_robot_dog_ros(app)
demo_protocol_hotswap(app)
demo_multi_device_manager(app)
demo_fault_injection(app)
demo_custom_extension(app)
print(f"{SEP}")
print(f" ✅ 所有演示通过!无人系统控制层模块运行正常")
print(f" 模块统计:")
print(f" 协议适配器 : MAVLinkAdapter / ROSAdapter / SimulationAdapter")
print(f" 控制器 : UAVController / RobotDogController / USVController")
print(f" 管理器 : UASManager支持 {6} 台设备并发)")
print(f" 支持指令数 : {len(CommandType)}")
print(f"{SEP}\n")
if __name__ == "__main__":
main()