Simulink与Python的UDP通信
本文总结一下用UDP实现simulink与python的通信,重点在于Python udp接收端的代码(python socket的用法见上一篇:python中socket模块基础用法)
其实原理是非常直接的,首先是用localhost作为IP地址,端口自定义(1024 ~ 65535)用Simulink的内置UDP发送模块发送信号(本文中用的是离散的正弦信号)给python接收端即可。
- 搭建Simulink框图
在想要发送的信号数据的框图后直接添加udp send模块即可。
2. 解包simulink传出的数据
2.1 导入python struct模块
Simulink默认传出来的数据是double格式,所以需要在python中添加解码double数据类型的代码,MALTAB中的double数据类型与C中的double类型一致,所以Python内置的struct库使用起来会很有效。(多亏网络调试助手才能知道这个思路!!)
2.2 解包单个信号
struct模块的目的就是在python与C程序通信的时候,将C的struct数据结构转化为python能够识别的类型。本例中就是将MATLAB的double类型进行解包。对应语句为:recv_msg_decode = struct.unpack(“d”, recv_msg)[0],这里的recv_msg是python程序接收到的原始信号(bytes类型),struct.unpack(“d”, recv_msg)的意思就是以”d”(double类型)对recv_msg进行解包,返回一个元组,第一个数为解包后的数值。
cmd中显示接收到的数据:
接收到数据后用matplotlib对其绘图可得以下图形:
2.3 解包多个信号
上面说过,在解包单个信号的时候,unpack函数会返回一个size为1的元组。如果要传输多个double型数据(这里传输3个),可以在上面语句的基础上直接改为:recv_msg_decode = struct.unpack(“3d”, recv_msg),即改变unpack传入的string参数,再用for循环遍历返回的元组即可。
附:解包单个正弦信号的完整代码(python)
#!/usr/bin/env python# -*- coding: utf-8 -*import socket, struct, osimport numpy as npimport matplotlib.pyplot as pltdef main():# -------------------------------- Initializing --------------------------------------------# Create a socketudp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# Bind the IP address and port.localaddr = ("127.0.0.1", 54320)udp_socket.bind(localaddr)# Create an increment for while loopcount = 0# Create a list to restor the data from simulink.data_collect = []# Create a path to save figure:path = 'Your Path Here'print("Please open the Simulink file under the current working directory")print("The program is waiting until you run the Simulink file.")#----------------------------------- Data Receiving ----------------------------------------# Using a loop to receive data from Simulinkwhile count < 101: # Can be modified by (simulationTime/sampleTime).# Start to receive data from Simulink.recv_data = udp_socket.recvfrom(1024)#print(recv_data)# recv_data will return tuple, the first element is DATA, and the second is address informationrecv_msg = recv_data[0]send_addr = recv_data[1]# Decode the data from Simulink whose type is double and return a tuplerecv_msg_decode = struct.unpack("d", recv_msg)[0]# Restore the data to a list:data_collect.append(recv_msg_decode)# Set the condition to jump out of this loop ???# Print the address information and the received dataprint("Number from MATLAB %s is : %s" % (str(send_addr), recv_msg_decode))count += 1# Close the udp socket.udp_socket.close()# ------------------------------------ Visualization -----------------------------------------------# Set the time axis, 10 is the simulation end time that can be modified by user.index = list(np.linspace(0, 10, (len(data_collect))))plt.plot(index, data_collect)plt.title("Signal Received from Simulink")plt.xlabel("Time")plt.ylabel("Received Data")plt.savefig(os.path.join(path, 'data_figure.png'), dpi=600)print("Close the figure to restart.")plt.show()if __name__ == "__main__":main()
(代码中循环的部分暂且用总的(仿真时间/采样时间)+1得到while后的参数,另外一种方法是导入time库,用time.sleep(0.1)可以识别KeyboardInterruption)
ref
https://blog.csdn.net/qq_41871826/article/details/104172653
