前言:

最近在写使用UE4联动“六轴平台”的控制程序,这里就用到了机器硬件交互和计算机网络相关的知识。拿到硬件厂商的网络协议后,就要根据协议编写相关代码,下面记录一下开发过程。

网络字节序: 首先要明白和机器通讯中所传输的数据一般为字节流,即网络字节序,顾名思义就是字节的顺序。一般系统都会采用 UDP协议,UDP的好处就是机器只管接收就行。

进行 UDP广播: 在开始前,你需要了解如何使用UE4进行 UDP广播数据,你可以参考这篇文章“使用UE4原生模块进行简单UDP广播和数据接收”。

float转字节序: 直接上代码:这个函数可以将float类型的数据转为unsigned char类型的数组。 /*

  • Describe:将float类型数据转换为unsigned char数组(即网络字节序)
  • Paramfvalue待转换数据
  • Paramarr传入的字节序
  • ParamIndex从数组的第几位开始转换,默认为0 **/
1
2
3
4
void AUDPSend::ftoc(float fvalue, int Index, unsigned char* arr)
{
unsigned char* pf;
unsigned char* px;

unsigned char i; //计数器 pf = (unsigned char*)&fvalue; /unsigned char型指针取得浮点数的首地址/ px = arr; /字符数组arr准备存储浮点数的四个字节,px指针指向字节数组arr/ for (i = Index; i < Index + 4; i++) { *(px + i) = *(pf + (i - Index)); /使用unsigned char型指针从低地址一个字节一个字节取出/ }

示例: 1、假设一个六维平台采用的是 UDP协议,且接收的数据结构如下: USTRUCT(BlueprintType)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
struct FDataToVice
{
GENERATED_USTRUCT_BODY()

UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "DataToVice")
int sMark = 55;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "DataToVice")
int sComd = 0;
int sRepa[2] = { 0 };
float sAtti[6];
float sVelo[6] = { 0 };
float sAcce[3] = { 0 };
};

2、进行 UDP广播之前,应该先构造需要广播的数据。意思就是将结构体中的数据转为字节流。

创建一个“unsigned char”类型数组: unsigned char ViceData[64] = {0};

用于构造数据的函数如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void AUDPSend::MakeViceData(FTransform Transform_, FDataToVice DataToVice_)
{
DataToVice_.sAtti[0] = Transform_.Rotator().Pitch;
DataToVice_.sAtti[1] = Transform_.Rotator().Yaw;
DataToVice_.sAtti[2] = Transform_.Rotator().Roll;
DataToVice_.sAtti[3] = Transform_.GetTranslation().X;
DataToVice_.sAtti[4] = Transform_.GetTranslation().Y;
DataToVice_.sAtti[5] = Transform_.GetTranslation().Z;

ViceData[0] = DataToVice_.sMark;
ViceData[1] = DataToVice_.sComd;
ViceData[2] = DataToVice_.sRepa[0];
ViceData[3] = DataToVice_.sRepa[1];

//float Vector_X = Transform_.GetTranslation().X;

//ftoc(Vector_X, 4, ViceData);

ftocLoop(DataToVice_.sAtti, 4, 6, ViceData);
ftocLoop(DataToVice_.sVelo, 28, 6, ViceData);
ftocLoop(DataToVice_.sAcce, 52, 3, ViceData);
}
void AUDPSend::ftocLoop(float Value[],int BeginIndex, int length, unsigned char* arr)
{
for (int i = 0; i < length; i++)
{
ftoc(Value[i], BeginIndex, ViceData);

BeginIndex += 4;
}
}

开始UDP广播数据:(建议先阅读文章“使用UE4原生模块进行简单UDP广播和数据接收”) 在蓝图中先调用“构造数据的函数MakeViceData”,再调用函数“SendUDPMessages”就可以开始广播数据了

1
2
3
4
5
6
7
8
9
bool AUDPSend::SendUDPMessages(FString ToSend)
{
if (!SenderSocket)
{
//ScreenMsg("No sender socket");
return false;
}

int32 BytesSent = 0;

SenderSocket->SendTo(ViceData, 64, BytesSent, *RemoteAddr);//发送给远端地址

if (BytesSent <= 0) {

1
2
3
4
5
6
7
8
const FString Str = "Socket is valid but the receiver received 0 bytes, make sure it is listening properly!";
UE_LOG(LogTemp, Error, TEXT("%s"), *Str);
ScreenMsg(Str);
return false;
}

return true;
}

使用网络抓包工具查看网络中的字节数据:

可以使用网络抓包工具对网络中的数据进行查看,网上这种工具很多,我这里使用的是“NetAssist”,(安装包放在了文章结尾处的百度云链接中,见资源01)。 下载好直接运行即可,UDP开始广播后,输入对应的 IP和端口,开始监听就可以看到数据了。如图1-1所示: ef9bf445_image1

图1-1

参考链接:

https://blog.csdn.net/u013457167/article/details/78323298

资源链接:

链接:https://pan.baidu.com/s/1RB_fYao2CCyNeKao5L3p8Q 提取码:Mcao