1. 车载CAN总线报文采集与解析

任务目标

本案例搭建一个可运行的车联网通信仿真环境,用于模拟车辆与路侧单元(RSU)之间的V2I通信过程。环境基于Python实现,包含车辆节点、RSU节点和通信信道三个核心组件,能够完成消息的发送、接收与传输延迟统计,为后续协议栈实验提供基础仿真平台。

环境依赖

需要Python 3.8+,无需第三方库,仅使用标准库random、time和dataclasses。代码在单文件内完成,可直接运行。

完整实现

import random
import time
from dataclasses import dataclass, field
from typing import List, Dict

@dataclass
class Vehicle:
    """车辆节点:周期发送BSM安全消息"""
    id: int
    position: float  # 道路位置(米)
    speed: float     # 速度(m/s)
    sent_count: int = 0
    
    def generate_bsm(self) -> Dict:
        """生成基本安全消息(BSM)"""
        self.sent_count += 1
        return {
            "type": "BSM",
            "vehicle_id": self.id,
            "position": self.position,
            "speed": self.speed,
            "timestamp": time.time()
        }

@dataclass
class RSU:
    """路侧单元:接收消息并记录延迟"""
    id: int
    position: float
    received: List[Dict] = field(default_factory=list)
    
    def receive(self, msg: Dict, delay: float):
        msg["delay_ms"] = round(delay * 1000, 2)
        self.received.append(msg)

class Channel:
    """通信信道:模拟传播延迟与丢包"""
    def __init__(self, loss_rate: float = 0.1):
        self.loss_rate = loss_rate
    
    def transmit(self, sender_pos: float, receiver_pos: float, msg: Dict) -> float | None:
        """返回传播延迟(秒),丢包返回None"""
        if random.random() < self.loss_rate:
            return None
        distance = abs(sender_pos - receiver_pos)
        # 假设传播速度200m/ms(简化模型)
        return distance / 200_000

def run_simulation(duration: float = 5.0, interval: float = 0.5):
    """运行仿真:车辆每interval秒发送一次BSM"""
    # 初始化节点
    vehicle = Vehicle(id=1, position=100.0, speed=20.0)
    rsu = RSU(id=1, position=500.0)
    channel = Channel(loss_rate=0.1)
    
    start = time.time()
    while time.time() - start < duration:
        # 车辆位置随时间更新
        vehicle.position += vehicle.speed * interval
        
        # 生成并发送消息
        bsm = vehicle.generate_bsm()
        delay = channel.transmit(vehicle.position, rsu.position, bsm)
        
        if delay is not None:
            rsu.receive(bsm, delay)
        else:
            print(f"消息 {bsm['vehicle_id']} 在传输中丢失")
        
        time.sleep(interval)
    
    # 输出统计结果
    print(f"\n=== 仿真结束 ===")
    print(f"车辆发送消息总数: {vehicle.sent_count}")
    print(f"RSU成功接收: {len(rsu.received)}")
    print(f"丢包率: {(vehicle.sent_count - len(rsu.received)) / vehicle.sent_count:.1%}")
    
    if rsu.received:
        delays = [m["delay_ms"] for m in rsu.received]
        print(f"平均传输延迟: {sum(delays)/len(delays):.2f} ms")
        print(f"最大延迟: {max(delays):.2f} ms")
        print(f"最小延迟: {min(delays):.2f} ms")
    
    return vehicle, rsu

if __name__ == "__main__":
    # 固定随机种子保证可复现
    random.seed(42)
    run_simulation(duration=3.0, interval=0.5)

运行方式

将代码保存为v2i_sim.py,在终端执行:

python v2i_sim.py

验证方法

程序运行后应输出仿真统计信息。通过以下条件判断仿真环境是否搭建成功:

  • 车辆发送消息总数约为duration/interval(3秒/0.5秒=6条),由于循环计时存在微小偏差,实际值可能为5~7条;
  • RSU接收消息数小于等于发送总数,丢包率接近设定的10%(因随机种子固定,每次运行结果一致);
  • 延迟值随车辆位置变化:车辆靠近RSU时延迟减小,远离时增大,且所有延迟值在合理范围内(约0.2~2ms)。

若输出显示发送总数大于0、接收数小于等于发送数、延迟数值非负,则说明车辆节点、RSU节点和信道三个组件均正常工作,仿真环境搭建完成。

车辆 RSU BSM消息 (位置/速度/时间戳) 传播延迟 = 距离 / 200m/ms 丢包率: 10% (随机丢弃) 位置: 100m 位置: 500m

上图展示了仿真环境的核心通信模型:车辆沿道路行驶并周期性发送BSM消息,RSU固定在500m处接收消息。信道根据两者距离计算传播延迟,并以10%概率模拟丢包。该模型为后续协议栈实验提供了基础的消息传递与延迟统计能力。