当前位置: 首页 > news >正文

0119

好的,明白了!根据你的确认,我来提供完整的实现代码。

完整修改方案

一、UdpSocketServer.h 修改

在文件中添加以下内容:

1. 添加委托声明(在现有委托声明区域,建议放在 FOnMissileGroupDataReceived 之后)

DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams(FOnLoiteringMunitionGroupDataReceived, const TArray<uint8>&, MunitionIds, const TArray<uint8>&, MunitionTypes, const TArray<uint8>&, MunitionStates, const TArray<FVector>&, MunitionPositions,const TArray<FRotator>&, MunitionRotations
);

2. 添加委托实例(在public区域,建议放在 OnMissileGroupDataReceived 之后)

UPROPERTY(BlueprintAssignable, Category = "UDP Loitering Munition Delegate")
FOnLoiteringMunitionGroupDataReceived OnLoiteringMunitionGroupDataReceived;

3. 添加解析函数声明(在 ParseMissileGroupData 之后)

void ParseLoiteringMunitionGroupData(const TArray<uint8>& Data, FString& OutStr);

二、UdpSocketServer.cpp 修改

1. 在 DataRecv 函数的 switch 语句中添加 case 5

找到 DataRecv 函数中的 switch 语句,在 case 4 之后添加:

case 5:
{FString DebugStr;ParseLoiteringMunitionGroupData(ReceivedData, DebugStr);str = DebugStr;success = true;break;
}

2. 实现 ParseLoiteringMunitionGroupData 函数

在文件末尾(建议放在 ParseMissileGroupData 函数之后)添加:

void UUdpSocketServer::ParseLoiteringMunitionGroupData(const TArray<uint8>& Data, FString& OutStr)
{int32 Offset = 1;uint8 MunitionCount = Data[Offset];Offset += 1;const int32 SingleMunitionDataSize = 51;  // 1(ID) + 1(Type) + 1(State) + 24(Position) + 24(Rotation)if ((Data.Num() - Offset) < (MunitionCount * SingleMunitionDataSize)){UE_LOG(LogTemp, Warning, TEXT("Insufficient data for loitering munition group. munition count: %d, hope length: %d, fact length: %d"),MunitionCount, Offset + MunitionCount * SingleMunitionDataSize, Data.Num());OutStr = TEXT("Error: Insufficient data for loitering munition group");return;}TArray<uint8> MunitionIds;TArray<uint8> MunitionTypes;TArray<uint8> MunitionStates;TArray<FVector> MunitionPositions;TArray<FRotator> MunitionRotations;FString GroupStr = TEXT("Loitering Munition Group: ");for (int32 i = 0; i < MunitionCount; ++i){uint8 MunitionId = Data[Offset];uint8 MunitionType = Data[Offset + 1];uint8 MunitionState = Data[Offset + 2];// 解析位置double X = 0, Y = 0, Z = 0;FMemory::Memcpy(&X, &Data[Offset + 3], sizeof(double));FMemory::Memcpy(&Y, &Data[Offset + 11], sizeof(double));FMemory::Memcpy(&Z, &Data[Offset + 19], sizeof(double));// 解析姿态double Yaw = 0, Pitch = 0, Roll = 0;FMemory::Memcpy(&Yaw, &Data[Offset + 27], sizeof(double));FMemory::Memcpy(&Pitch, &Data[Offset + 35], sizeof(double));FMemory::Memcpy(&Roll, &Data[Offset + 43], sizeof(double));FVector Position(static_cast<float>(X), static_cast<float>(Y), static_cast<float>(Z));FRotator Rotation(static_cast<float>(Pitch), static_cast<float>(Yaw), static_cast<float>(Roll));GroupStr += FString::Printf(TEXT("[ID: %d, Type: %d, State: %d, Pos: %s, Rot: %s] "),MunitionId, MunitionType, MunitionState, *Position.ToString(), *Rotation.ToString());Position = ConvertUEOffset(Position);if (MunitionId > 0)  // 0 为无效巡飞弹{MunitionIds.Add(MunitionId);MunitionTypes.Add(MunitionType);MunitionStates.Add(MunitionState);MunitionPositions.Add(Position);MunitionRotations.Add(Rotation);}Offset += SingleMunitionDataSize;}OutStr = GroupStr;if (bIsLogReceivedPackage)UE_LOG(LogTemp, Warning, TEXT("the data parse loitering munition group is: %s"), *OutStr);// 广播委托OnLoiteringMunitionGroupDataReceived.Broadcast(MunitionIds, MunitionTypes, MunitionStates, MunitionPositions, MunitionRotations);
}

三、Python 测试脚本

创建一个测试脚本来验证功能:

import socket
import struct
import timedef send_loitering_munition_group(sock, target_ip, target_port, munitions_data):"""发送巡飞弹组数据munitions_data: list of dict, 每个dict包含 id, type, state, position(x,y,z), rotation(yaw,pitch,roll)"""message_type = 5munition_count = len(munitions_data)# 构建数据包packet = struct.pack('BB', message_type, munition_count)for munition in munitions_data:# 基本信息: ID, Type, Statepacket += struct.pack('BBB', munition['id'], munition['type'], munition['state'])# 位置: X, Y, Z (double)packet += struct.pack('ddd', munition['position'][0],munition['position'][1],munition['position'][2])# 姿态: Yaw, Pitch, Roll (double)packet += struct.pack('ddd',munition['rotation'][0],  # Yawmunition['rotation'][1],  # Pitchmunition['rotation'][2])  # Rollsock.sendto(packet, (target_ip, target_port))print(f"发送巡飞弹组数据: {munition_count} 个巡飞弹")print(f"数据包大小: {len(packet)} 字节")# 测试代码
if __name__ == "__main__":# 配置TARGET_IP = "127.0.0.1"  # 修改为你的目标IPTARGET_PORT = 8888        # 修改为你的目标端口# 创建UDP socketsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 测试数据:3个巡飞弹test_munitions = [{'id': 1,'type': 1,'state': 0,'position': [100.0, 200.0, 50.0],'rotation': [45.0, 10.0, 5.0]  # Yaw, Pitch, Roll},{'id': 2,'type': 2,'state': 1,'position': [150.0, 250.0, 60.0],'rotation': [90.0, 15.0, -5.0]},{'id': 3,'type': 1,'state': 0,'position': [200.0, 300.0, 70.0],'rotation': [135.0, 20.0, 0.0]}]try:while True:send_loitering_munition_group(sock, TARGET_IP, TARGET_PORT, test_munitions)# 更新位置和姿态(模拟移动)for munition in test_munitions:munition['position'][0] += 1.0munition['position'][1] += 0.5munition['rotation'][0] = (munition['rotation'][0] + 1) % 360time.sleep(0.1)  # 100ms发送一次except KeyboardInterrupt:print("\n停止发送")finally:sock.close()

四、修改总结

修改的文件:

  1. UdpSocketServer.h - 添加委托和函数声明
  2. UdpSocketServer.cpp - 添加解析逻辑

关键点:

  • ✅ 复用 NumMissilesPerPacket 配置
  • ✅ 使用消息类型 5
  • ✅ 数据包格式:1(消息类型) + 1(数量) + N×51(每个巡飞弹数据)
  • ✅ 仅实现 Group 版本
  • ✅ 包含位置和姿态数据
  • ✅ 支持坐标转换 ConvertUEOffset

数据包结构:

[消息类型:1字节] [数量:1字节] [巡飞弹1数据:51字节] [巡飞弹2数据:51字节] ...每个巡飞弹数据(51字节):
- ID: 1字节
- Type: 1字节  
- State: 1字节
- Position X: 8字节(double)
- Position Y: 8字节(double)
- Position Z: 8字节(double)
- Yaw: 8字节(double)
- Pitch: 8字节(double)
- Roll: 8字节(double)

这样修改后,你就可以在蓝图中订阅 OnLoiteringMunitionGroupDataReceived 委托来接收和处理巡飞弹数据了!

http://www.jsqmd.com/news/269244/

相关文章:

  • Doris数据过期策略:自动清理历史数据
  • 如何高效管理项目需求变更?实战技巧与方法解析
  • 基于python+Vue的学生交流互助平台 学习兴趣小组任务打卡系统8y1o61qk
  • 亚马逊买家号常见异常解析:为什么账号会逐步受限?
  • 【 每天学习一点算法 2026/01/19】位1的个数
  • 基于vue和python的医院预约挂号系统的设计与实现
  • python基于vue的积分制零食商城自选平台 (三端:管理端+用户PC端+用户小程序端)
  • python基于人脸识别的互联网课堂学生考勤系统
  • 【机翼】三维机翼几何进行耦合静态气弹性分析Matlab仿真
  • 创客匠人视角:创始人 IP 与智能体的协同范式革命,重新定义知识变现的价值边界
  • 计算机毕业设计springboot基于Java的网上花店系统 计算机毕业设计springboot基于Java的网上花店系统 Java技术驱动的Spring Boot网上花店平台开发
  • 三维动态避障路径规划:基于山羊优化算法(Goat Optimization Algorithm, GOA)融合动态窗口法DWA的无人机三维动态避障方法研究附MATLAB代码
  • 创客匠人深度解析:创始人 IP 打造的智能体基建逻辑,重构知识变现底层规则
  • 【图像融合】基于小波变换红外和可见光图像融合(含评价指标)附Matlab代码
  • python基于大数据的自助餐厅菜品供应优化与分析预测系统 数据分析可视化大屏系统e8737qr2
  • 创客匠人洞察:智能体重构 IP 变现逻辑,创始人 IP 如何实现从 “单次付费” 到 “终身价值”
  • WebDataset使用指南:构建高效深度学习数据管道
  • 2026 年适合追剧吃的零食推荐、挑选技巧与选购指南(我常备的“追剧薯条”是浪味仙) - Top品牌推荐
  • Transformer完全入门指南:从零开始理解
  • 【必学收藏】一文讲透AI Agent、Agentic Workflow与Agentic AI:三个层级看懂AI自主行动完整体系(附6篇核心论文)
  • 广西产业带背后的真实情况:不要再把“东盟展厅”当成是源头工厂了!
  • Fastlane 结合 开心上架,构建跨优秀的平台可发布的 iOS 自动化流水线实践
  • python基于智能AI技术的教学辅助问答系统
  • Mac多显示器支持:TESmart USB-C KVM(搭载DisplayLink技术)全面解析
  • 收藏!2026大模型行业就业趋势全景报告:小白程序员转型必看
  • Oracle:增加十分钟
  • 【滤波跟踪】基于卡尔曼滤波实现分布式传感器采集目标的位置或信号强度(RSSI)数据目标运动轨迹进行实时预测与校正,输出跟踪误差(如平均距离误差、RMSE)并可视化跟踪结果matlab代码
  • 一文看懂:MES价值,MES系统对企业的生产管理有哪些改进?
  • 猴子
  • Java:POST请求发送的消息体太大