【MATLAB】【装卸臂项目】C++利用UDP与Simulink通信

1、C++利用UDP socket发送结构体数据

之前也看了一些博客,sendto只能发送char型数据,所以如果要发送非字符型的数据,要先转换一下。

这两条代码强制转化了结构体数据,如果要使用其他类型的数据,变换方式也类似。

camcoord udpPack;
char *pPack = (char *)&udpPack;

Sendto函数原型

 

int
WSAAPI
sendto(
    _In_ SOCKET s,
    _In_reads_bytes_(len) const char FAR * buf,
    _In_ int len,
    _In_ int flags,
    _In_reads_bytes_(tolen) const struct sockaddr FAR * to,
    _In_ int tolen
    );

s:已建好连线的socket, 如果利用UDP协议则不需经过连线操作.

buf: 指向欲连线的数据内容, 这里就是结构体的指针

len:数据的大小,在本例中数组里面的内容是double型的,每一个double分配8个char,所以 len=4*8=32.

         一定要根据数据的大小合理设置长度,否则数据会乱。

flags :一般设0

to :用来指定欲传送的网络地址, 结构sockaddr 参考bind().

tolen :为sockaddr 的结果长度.

 

UDP 发送端的代码转自

https://blog.csdn.net/qq_29422251/article/details/53390587

#include <stdio.h>
#include <string>
#include <iostream>
#include <winsock.h>
using namespace std;
//创建新的套接字之前需要调用一个引入Ws2_32.dll库的函数,否则服务器和客户端连接不上
#pragma comment(lib,"ws2_32.lib")
typedef struct CamCoord {
	double a;//the angle of camera turning
	double x;
	double y;
	double z;
}camcoord, *pcam;


WSADATA wsaData;                                    //指向WinSocket信息结构的指针
SOCKET serSocket;                                //创建套接字
SOCKADDR_IN serUdpServ, clientAddr;                              //指向通信对象的结构体指针  

int main(int argc, char* argv[])
{
	camcoord udpPack;
	char *pPack = (char *)&udpPack;
	//*************************** 第一步初始化Winsock   *****************************//
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)     //进行WinSocket的初始化
	{
		printf("Can't initiates windows socket!Program stop.\n");//初始化失败返回-1
		return -1;
	}

	//********************   第二步建立一个数据报类型的UDP套接字  ******************//
	serSocket = socket(PF_INET, SOCK_DGRAM, 0);
	serUdpServ.sin_family = AF_INET;
	serUdpServ.sin_addr.s_addr = inet_addr("127.0.0.1");
	//saUdpServ.sin_addr.s_addr = htonl ( INADDR_BROADCAST );
	serUdpServ.sin_port = htons(8001);               //发送用的端口,可以根据需要更改

	clientAddr.sin_family = AF_INET;
	clientAddr.sin_port = htons(4337);
	clientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	if (bind(serSocket, (sockaddr *)&serUdpServ, sizeof(serUdpServ)) == SOCKET_ERROR)
	{
		printf("bind error !");
		closesocket(serSocket);
		return 0;
	}
	/*
	if (Communicarte() == 0||Communicarte() == -1)
		return 0;
	*/
	udpPack.a = 52.12221;
	udpPack.x = 15.23221;
	udpPack.y = 65.34221;
	udpPack.z = 65.34221;

	while (1) 
	{
		Sleep(1000);
		//**********************  第三步使用sendto函数进行通信    *************************// 
		sendto(serSocket, pPack, 32, 0, (struct sockaddr*)&clientAddr, sizeof(clientAddr));
	}
	//*********************   第四步关闭socket  ***************************************//
	closesocket(serSocket);         //关闭监听socket
	WSACleanup();
	return 0;
}

2、SImulink框架

 

 

3、UDP receive模块参数设置

几个需要注意的地方:

Block sample time是数据的采样时间,这里取0.001和C++中轨迹规划的时间间隔保持一致就可以保证时间同步了,不需要再

real-time sychronization 保证时间让仿真时间与实际同步,反而是这个模块有最大丢包报错功能,如果编译时间慢了错过了接收数据会报错,有点麻烦。

UDP地址配置:

Local address 可以通过查看IPV4地址得到,但是不同的无线网络环境下,IPV4地址总是变化的,可能今天改好的端口,明天就报错了。所以我在做调试的时候用了一个调试助手,可以自动读取本地主机的地址,比较方便。(之前做通信连接的时候也借助了这个工具)【NetAssist网络调试助手】

 Byte order:数据发送的时候是大端序还是小端序,如果数据乱码,需要检查一下这里。

 

4、 Simulink中timeseries类的导入

目前在试过的所有模块中,基本能够确定timeseries只能通过to workspace或者from workspace保存或引用自workspace。

如果想要直接利用simulink中的模块产生timeseries基本不可能,好在UDP导出的数据本身就是timeseries类型的,不然还真不知道怎么弄。

 

如果需要模拟timeseries那样按照固定的时间步长在simulink仿真过程中传输数据,只能通过设置Fixed-step size和引入counter模块方式实现。【仅有来自MATLAB中文论坛的资料,可能是唯一能够实现的方法】(https://www.ilovematlab.cn/thread-473355-1-1.html

 

5、Simscape导入URDF文件开始仿真

https://blog.csdn.net/xiaohejiaoyiya/article/details/104954035

 

 

 

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值