背景

        在自动驾驶项目开发中,需要同时运行多个模块来保证实时性和降低计算负载。这些模块包括感知模块、决策模块、控制模块等。为了处理大量的数据和实时反馈,通常需要使用高端配置的电脑进行仿真场景搭建和算法运行。

主机配置:

AMD Ryzen 9 5900HX with Radeon Graphics 3.30 GHz

32.0 GB(27.9 GB可用)
显卡为 3080(16GB)

        进行驾驶场景搭建以及算法运行的电脑配置如上,在项目思路中,需要将车辆感知数据进行图形化输出传递给驾驶人,在实际仿真操作中,需要当车辆传感器传回相关感知信息后,算法对感知信息进行处理,将前方车路风险进行量化,并将量化的结果进行图形化输出至显示设备中。

        但是在进行输出图形化显示计算的仿真场景过程中,出现延时高的问题,控制输入并不能及时到仿真软件中的车辆模型中。如图所示,并且电脑出现明显卡顿。

 所以采用旭日X3派实现L3自动驾驶场景下并行实时运算,对图形化的数据进行处理。

        根据查阅相关数据如图所示,旭日X3派是一款高性能的嵌入式计算机,具有较强的计算能力和低功耗特性。通过将部分函数发送给旭日X3派进行并行运算,从而降低电脑的计算负载和延迟,并提升系统的实时性和稳定性。

思路

        可以将需要进行实时运算的部分代码编写为独立的函数,并使用网络协议(如TCP/IP)将该函数发送给旭日X3派进行并行处理。即“分布式计算”,这样能够充分利用多台计算机的处理能力,提高程序的运算速度和效率。这里需要确保网络传输的可靠性和数据的安全性。

        但是如何实现这一功能是一个全新的问题,所以根据查阅资料拟定一个大致的想法思路,并依照这一思路进行实现。

要实现将部分函数发送给旭日X3派进行并行实时运算,以下是一个初步的实现想法:

  1. 将需要在旭日X3派上实现的函数转换为可执行文件或动态库。

  2. 在电脑上编写主程序,包括与旭日X3派的通信逻辑,并将需要发送给旭日X3派的参数进行打包。

  3. 通过网络连接将打包后的参数和可执行文件或动态库发送给旭日X3派。

  4. 旭日X3派接收到参数和可执行文件或动态库后,执行相应的计算,并将结果返回给电脑。

  5. 电脑接收到旭日X3派返回的结果后,继续进行主程序的计算。

然后在这五个步骤的基础上,在实现过程中要确保通信的可靠性和安全性,例如使用加密技术保护数据传输过程中的机密信息。同时,还需要根据实际需求选择合适的通信方式和协议,例如TCP、UDP、HTTP等。

        要设置通信方式和协议,我们需要考虑到进行L3自动驾驶的实验中,可靠性和实时性是最主要的,而数据加密由于是实验环境所以暂不考虑。

        下面列出几种常见的通信方式和协议:

  1. TCP/IP:TCP是一种可靠的面向连接的传输协议,通常用于需要确保数据可靠传输的场景。IP是一种网络层协议,用于将数据包从源主机路由到目的主机。

  2. UDP:UDP是一种无连接的传输协议,通常用于对传输速度有要求,但数据可靠性不是最高优先级的场景。

  3. HTTP/HTTPS:HTTP是一种基于TCP协议的应用层协议,常用于Web应用中。HTTPS是在HTTP协议的基础上增加了SSL/TLS加密的安全协议。

  4. MQTT:MQTT是一种轻量级的消息传输协议,常用于物联网场景中,支持发布订阅模式和点对点模式。

    在本项目的场景设计中,我们只需要在旭日X3派中处理传输过去的感知信息获得风险值并将风险值图形化输出到显示器中,所以只需要保证实时性要求,于是选择UDP协议。UDP是一种无连接的传输协议,不进行可靠传输和重发保证,但其具有较低的延迟和较高的吞吐量特性,并且适合用于广播和多播等场景。

    在我们设计的L3自动驾驶系统中,由于各个模块需要及时地共享数据,因此需要选择具备较高实时性的通信协议来进行数据传输。UDP协议可以满足实时性要求,对于实时性要求非常高的应用场景,使用UDP协议能够快速传输数据,以保证系统的实时性和稳定性。

    在旭日X3派中实现UDP协议传输函数,需要使用一些网络编程相关的工具和库。

    这里我们使用Python开发相关程序,可以使用socket库来实现UDP协议传输函数。

    下面是一个简单的UDP发送函数示例:

    import socket
    
    def udp_send(data, ip, port):
        # 创建UDP套接字
        udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
        # 发送数据
        udp_socket.sendto(data, (ip, port))
    
        # 关闭套接字
        udp_socket.close()

UDP 不是点对点,不存在请求连接和受理过程,所以也不需要创建子进程一一对应,因此在某种意义上无法明确区分服务器端和客户端,所以我将运行自动驾驶算法以及搭载自动驾驶场景的主机称为服务器端。

首先实现的是实现向目标IP地址为192.168.1.10(旭日X3派ip地址),端口号为9999发送一个[OBJ_ID, OBJ_Class, OBJ_S_X, OBJ_S_Y, OBJ_S_Z, OBJ_S_Velocity, OBJ_Length,OBJ_Width, OBJ_Height](车辆传感器获取的数据)的列表。

import socket

def send_obj_data(ip, port, obj_data):
    # 创建UDP套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 构造数据包
    data = ','.join(str(x) for x in obj_data).encode()

    # 发送数据包
    udp_socket.sendto(data, (ip, port))

    # 关闭套接字
    udp_socket.close()

在该函数中,首先创建了一个UDP套接字。然后,将[obj_id, obj_class, obj_s_x, obj_s_y, obj_s_z, obj_s_velocity, obj_length, obj_width, obj_height]列表转换成字符串,并用逗号分隔。最后,使用sendto函数将字符串数据包发送给指定的IP地址和端口号。注意,数据需要经过.encode()方法转换成二进制形式。发送完成后,使用close函数关闭UDP套接字。

调用该函数的方式如下:

obj_data = [OBJ_ID, OBJ_Class, OBJ_S_X, OBJ_S_Y, OBJ_S_Z, OBJ_S_Velocity, OBJ_Length, OBJ_Width, OBJ_Height]
send_obj_data('192.168.1.10', 9999, obj_data)

接下来实现数据的接收。

使用Python实现接收来自IP地址为192.168.1.100,端口号为9999的UDP数据包,并解析其中的[obj_id, obj_class, obj_s_x, obj_s_y, obj_s_z, obj_s_velocity, obj_length, obj_width, obj_height]列表,代码如下:

import socket
import struct

# 创建一个UDP套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定到本地地址和端口
server_address = ('192.168.1.10', 9999)
sock.bind(server_address)

while True:
    # 接收数据
    data, client_address = sock.recvfrom(1024)

    # 解析数据包
    obj_id, obj_class, obj_s_x, obj_s_y, obj_s_z, obj_s_velocity, obj_length, obj_width, obj_height = \
        struct.unpack('2i3f4i', data)

    # 处理解析后的数据,例如打印到控制台
    print(f"Received data from {client_address}:")
    print(f"obj_id: {obj_id}")
    print(f"obj_class: {obj_class}")
    print(f"obj_s_x: {obj_s_x}")
    print(f"obj_s_y: {obj_s_y}")
    print(f"obj_s_z: {obj_s_z}")
    print(f"obj_s_velocity: {obj_s_velocity}")
    print(f"obj_length: {obj_length}")
    print(f"obj_width: {obj_width}")
    print(f"obj_height: {obj_height}")
# 关闭套接字
udp_socket.close()

但是中间还存在一些问题没有解决,只是简单实现了数据传输,后续还需要继续优化与扩展。

在进行UDP通信时,需要注意以下几个方面:

  1. 数据包大小限制:UDP数据包大小有限制,通常不超过64KB。因此,在发送大量数据或者大文件时,需要进行分片或者压缩等处理。

  2. 丢失和乱序问题:由于UDP协议不进行可靠传输和重发保证,可能会导致部分数据包的丢失和乱序等问题。为了解决这些问题,可以在应用层进行超时重传和校验码校验等处理。

  3. 安全性问题:UDP协议不提供加密和认证等安全措施,因此需要在应用层采取一些安全机制,例如加密算法和数字签名等。

参考文章:

两个及其简单的TCPUDP程序,树莓派与pc间的通信_树莓派udp通信_怪我不能1v9的博客-CSDN博客

地平线旭日X3派试用-玩转串口通信 (horizon.ai)