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, os
import numpy as np
import matplotlib.pyplot as plt
def main():
# -------------------------------- Initializing --------------------------------------------
# Create a socket
udp_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 loop
count = 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 Simulink
while 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 information
recv_msg = recv_data[0]
send_addr = recv_data[1]
# Decode the data from Simulink whose type is double and return a tuple
recv_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 data
print("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