剩余任务功能分解

航弹院项目:

  • 解决移动问题

  • 界面-图表-指令发送界面-配置等等

  • 使用套接字发送指令与图片

  • 功能分解:

    • 指令控制功能:

      • 设计指令数据包.
      • 写到配置文件里并实时读取配置
      • 在飞机里增加套接字,用于针对性的发送指令
      • 写一个下拉菜单调用发送指令的功能
    • 实验科目功能

      • 读取配置文件,初始化实验场地
      • 在gamemode蓝图中?进行读取并放置的操作
  • 通信配置界面功能

    • 配置基础通信(基本实现)
  • 数据显示界面

    • 接受外部信息 动力学 节点数量 需要单开一个套接字
    • 读取图片并显示
  • 一期未完成功能

    • 地图问题(增加一个海洋,已有解决方案)

1.三维仿真运行是实时的,和飞机导弹等同步展示
2.三维场景下的飞机只需要展示飞机的状态轨迹携带两种弹药的数量 没写这个飞机携带的弹药数量

手搓激光雷达
手搓照相
应该是64线120°,角分辨利率0.18°,具体可以查查RSM1激光雷达的参数

动态导入:
RuntimeMeshLoader
gITFRuntime

下一步任务:
实现这个实验科目功能.

  • 设计配置文件内的保存结构1

  • 配置文件:读取实验科目的数量,然后生成对应数量的实验科目列表项.选第几个,就读取几号的配置.默认去读一号的位置1

  • 发现问题:在选择科目的时候,不同科目之间的飞机数量可能不同,而如果飞机是成组接收的话这个值也要变化。1

  • 逻辑:选择科目(默认科目1)-》读取场地中的无人机位置,清空原本的场地中的飞机导弹等-》根据读取到的科目里的飞机数量,修改一下套接字里的飞机数量1

实现这个控制指令功能

  • 创建一个发送的udp,用于发送指令1

  • 思考指令应该是什么,问gpt

  • 在udp套接字里留一个发送指令的接口1

  • **指令设计**

    数据包格式:

    [数据包标识 (1 byte), 目标无人机 (1 byte), 指令类型 (1 byte), 指令参数 (1 byte)]

    1. 起飞指令

    • 数据包标识: 0x05
    • 目标无人机: 例如 0x01(表示第1架无人机)
    • 指令类型: 0x01(起飞指令)
    • 指令参数: 0x00(起飞指令无额外参数,填充为 0x00
    • 总长度: 4 bytes
    • 格式: [0x05, 0x01, 0x01, 0x00]
    • 解释: 0x05 表示指令数据包,0x01 表示目标无人机,0x01 表示起飞,0x00 表示无额外参数。

    2. 模式选择指令

    • 数据包标识: 0x05
    • 目标无人机: 例如 0x01(表示第1架无人机)
    • 指令类型: 0x04(模式选择指令)
    • 指令参数: 模式编号
      • 0x01 姿态模式(Stabilize Mode)
      • 0x02 高度保持模式(AltHold Mode)
      • 0x03 自动模式(Auto Mode)
      • 0x04 悬停模式(Loiter Mode)
      • 0x05 引导模式(Guided Mode)
    • 示例格式(高度保持模式): [0x05, 0x01, 0x04, 0x02]
    • 解释: 0x05 表示指令数据包,0x01 表示目标无人机,0x04 表示模式选择,0x02 表示高度保持模式。

    3. 返航指令

    • 数据包标识: 0x05
    • 目标无人机: 例如 0x01(表示第1架无人机)
    • 指令类型: 0x02(返航指令)
    • 指令参数: 0x00(返航指令无额外参数,填充为 0x00
    • 总长度: 4 bytes
    • 格式: [0x05, 0x01, 0x02, 0x00]
    • 解释: 0x05 表示指令数据包,0x01 表示目标无人机,0x02 表示返航,0x00 表示无额外参数。

    4. 降落指令

    • 数据包标识: 0x05
    • 目标无人机: 例如 0x01(表示第1架无人机)
    • 指令类型: 0x03(降落指令)
    • 指令参数: 0x00(降落指令无额外参数,填充为 0x00
    • 总长度: 4 bytes
    • 格式: [0x05, 0x01, 0x03, 0x00]
    • 解释: 0x05 表示指令数据包,0x01 表示目标无人机,0x03 表示降落,0x00 表示无额外参数。

    5. 队形切换指令

    • 数据包标识: 0x05
    • 目标无人机: 例如 0x01(表示第1架无人机)
    • 指令类型: 0x05(队形切换指令)
    • 指令参数: 队形编号
      • 0x01 队形1
      • 0x02 队形2
      • 0x03 队形3
    • 示例格式(切换到队形2): [0x05, 0x01, 0x05, 0x02]
    • 解释: 0x05 表示指令数据包,0x01 表示目标无人机,0x05 表示队形切换,0x02 表示切换到队形2。

    ···
    bool SendCommand(uint8 TargetDrone, uint8 CommandType, const TArray& Params)
    {
    TArray DataToSend;
    DataToSend.Add(0x05); // 数据包标识
    DataToSend.Add(TargetDrone); // 目标无人机
    DataToSend.Add(CommandType); // 指令类型
    DataToSend.Append(Params); // 指令参数

      return SendBytes(DataToSend);    // 通过UDP发送
    

    }

    </details>
    
    

实现载具移动功能
场景中事先有载具 /动态生成 通信部分增加接收载具的部分具体留白 目前复用了导弹的信息
游戏开始创建一个套接字并绑定载具管理对象 1

实现能够接受多个套接字不同ip和端口接受数据的功能1
多创建几个套接字并命名,然后管理类绑定多个套接字1

设置界面对应更新,配置功能对应更新1

统计信息显示:通过UDP通信的方式接收来自外部的实验参数信息,如动力学数据(质量、转动惯量等),飞行状态(位置、姿态、速度等),不同节点数量(数字、半实物、实飞); 设计一个包1

区域删除功能1

这个统计信息展示部分,发来的动力学数据、飞行姿态等是和无人机

更新飞机收到的信息解析与委托。1
更新区域删除的信息 1

导弹和载具更新后 他们的删除操作重写1

通信协议
udp
飞机 包标志位uint8 1 飞机id uint8 飞机类型(侦察机/载机/布撒器) uint8 节点类型(数组/半实物/实飞)uint8 动力学数据(质量float、转动惯量float) 飞行状态(位置、姿态、速度 double9)
导弹 包标志位uint8 2 导弹id uint8 导弹类型uint8 导弹状态uint8 导弹位置double
3
载具 包标志位uint8 3 载具id uint8 载具类型uint8 载具状态uint8 载具位置double*3

mavlink
目标区域
目标点
GPS干扰区域
通信干扰区域
高威胁区

import socket
import struct
import math
import time
from threading import Timer

UDP 目标 IP 和端口

TARGET_IP = "192.168.1.105"
TARGET_PORT = 12345

创建 UDP socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

配置部分

config = {
'aircrafts': [{'id': 1, 'type': 1, 'node_type': 1, 'position': (0, 0, 10), 'speed': 10},
{'id': 2, 'type': 1, 'node_type': 1, 'position': (2, 0, 10), 'speed': 10},
{'id': 3, 'type': 1, 'node_type': 1, 'position': (4, 0, 10), 'speed': 10},
{'id': 4, 'type': 1, 'node_type': 1, 'position': (6, 0, 10), 'speed': 10},
{'id': 5, 'type': 1, 'node_type': 1, 'position': (8, 0, 10), 'speed': 10},
{'id': 6, 'type': 1, 'node_type': 1, 'position': (10, 0, 10), 'speed': 10},
{'id': 7, 'type': 1, 'node_type': 1, 'position': (12, 0, 10), 'speed': 10},
{'id': 8, 'type': 1, 'node_type': 1, 'position': (14, 0, 10), 'speed': 10},
{'id': 9, 'type': 1, 'node_type': 1, 'position': (16, 0, 10), 'speed': 10},
{'id': 10, 'type': 1, 'node_type': 1, 'position': (18, 0, 10), 'speed': 10}]
,
'missiles': [
{'id': 1, 'type': 1, 'position': (-8, 0, 20), 'speed': -10, 'state': 1}, # 最左
{'id': 2, 'type': 1, 'position': (-4, 0, 20), 'speed': -10, 'state': 1}, # 左
{'id': 3, 'type': 1, 'position': (0, 0, 20), 'speed': -10, 'state': 1}, # 中
{'id': 4, 'type': 1, 'position': (4, 0, 20), 'speed': -10, 'state': 1}, # 右
{'id': 5, 'type': 1, 'position': (8, 0, 20), 'speed': -10, 'state': 1}, # 最右
],
'vehicles': [
{'id': 1, 'type': 1, 'position': (-10, 0, 0), 'speed': -4, 'state': 1}, # 最左
{'id': 2, 'type': 2, 'position': (-5, 0, 0), 'speed': -4, 'state': 1}, # 左
{'id': 3, 'type': 3, 'position': (0, 0, 0), 'speed': -4, 'state': 1}, # 中
{'id': 4, 'type': 4, 'position': (5, 0, 0), 'speed': -4, 'state': 1}, # 右
{'id': 5, 'type': 5, 'position': (10, 0, 0), 'speed': -4, 'state': 1}, # 最右
],
'counts': {
'aircraft': 10, # 一个包发送3个飞机
'missile': 5, # 一个包发送5个导弹
'vehicle': 5 # 一个包发送5个载具
}
}

保存先前位置,用于计算偏航角

previous_positions = {ac['id']: (ac['position'][0], ac['position'][1]) for ac in config['aircrafts']}

def calculate_yaw(x1, y1, x2, y2):
dx = x2 - x1
dy = y2 - y1
return math.degrees(math.atan2(dy, dx))

def send_aircraft_data(aircrafts, t):
# 包标志位uint8 1 + 飞机数据
packet_data = struct.pack('=B', 1) # 包标志位1表示飞机数据包
for i in range(config["counts"]["aircraft"]):
# 如果索引在飞机列表范围内,使用实际的飞机数据
if i < len(aircrafts):
aircraft=aircrafts[i]
# for aircraft in aircrafts:
# 计算新位置(直线向前飞行)
x = aircraft['position'][0] + t * aircraft['speed']# X保持不变
y = aircraft['position'][1] # Y随时间向前
z = aircraft['position'][2] # Z保持不变

        # 计算偏航角
        pre_x, pre_y = previous_positions[aircraft['id']]
        yaw = calculate_yaw(pre_x, pre_y, x, y)
        pitch = 0.0
        roll = 0.0

        # 计算速度分量
        vel_x = 0.0
        vel_y = aircraft['speed']
        vel_z = 0.0

        # 更新先前位置
        previous_positions[aircraft['id']] = (x, y)
    else:
        x, y, z = 0, 0, 0
        yaw, pitch, roll = 0.0, 0.0, 0.0
        vel_x, vel_y, vel_z = 0.0, 0.0, 0.0
        # 打包单个飞机数据
    aircraft_data = struct.pack('=BBBff' + 'd' * 9,
                                aircraft['id'] if i < len(aircrafts) else 0,  # 飞机ID uint8
                                aircraft['type'] if i < len(aircrafts) else 0,  # 飞机类型 uint8
                                aircraft['node_type'] if i < len(aircrafts) else 0,  # 节点类型 uint8
                                1000.0,  # 质量 float
                                100.0,  # 转动惯量 float
                                x, y, z,  # 位置 double*3
                                roll, pitch, yaw,  # 姿态 double*3
                                vel_x, vel_y, vel_z  # 速度 double*3
                                )
    packet_data += aircraft_data

sock.sendto(packet_data, (TARGET_IP, TARGET_PORT))

def send_missile_data(missiles, t):
# 包标志位uint8 2 + 导弹数据
packet_data = struct.pack('=B', 2) # 包标志位2表示导弹数据包

for missile in missiles:
    # 计算新位置
    x = missile['position'][0]
    y = missile['position'][1] + t * missile['speed']
    z = missile['position'][2]

    # 打包单个导弹数据
    missile_data = struct.pack('=BBBddd',
                               missile['id'],  # 导弹ID uint8
                               missile['type'],  # 导弹类型 uint8
                               missile['state'],  # 导弹状态 uint8
                               x, y, z  # 位置 double*3
                               )
    packet_data += missile_data

sock.sendto(packet_data, (TARGET_IP, TARGET_PORT))

def send_vehicle_data(vehicles, t):
# 包标志位uint8 3 + 载具数据
packet_data = struct.pack('=B', 3) # 包标志位3表示载具数据包

for vehicle in vehicles:
    # 计算新位置
    x = vehicle['position'][0]
    y = vehicle['position'][1] + t * vehicle['speed']
    z = vehicle['position'][2]

    # 打包单个载具数据
    vehicle_data = struct.pack('=BBBddd',
                               vehicle['id'],  # 载具ID uint8
                               vehicle['type'],  # 载具类型 uint8
                               vehicle['state'],  # 载具状态 uint8
                               x, y, z  # 位置 double*3
                               )
    packet_data += vehicle_data

sock.sendto(packet_data, (TARGET_IP, TARGET_PORT))

def main():
start_time = time.time()

while True:
    t = time.time() - start_time

    # 发送飞机数据
    send_aircraft_data(config['aircrafts'], t)

    # 发送导弹数据
    # send_missile_data(config['missiles'], t)

    # 发送载具数据
    # send_vehicle_data(config['vehicles'], t)

    # 控制发送频率
    time.sleep(0.02)  # 20Hz的更新频率

if name == "main":
main()

posted @ 2024-10-17 11:27  灰色耳机  阅读(3)  评论(0编辑  收藏  举报