【IoT死磕系列】Day 9:架构一台“自动驾驶物流车”,看8种协议如何协同作战

目录

一、整车通信架构全景图

[二、 协议实战:数据的一生(从下单到车轮转动)](#二、 协议实战:数据的一生(从下单到车轮转动))

[场景 1:用户下单,车辆启动(MQTT vs HTTP)](#场景 1:用户下单,车辆启动(MQTT vs HTTP))

[场景 2:固件有 Bug,需要紧急修复(HTTP 的优势就体现出来了)](#场景 2:固件有 Bug,需要紧急修复(HTTP 的优势就体现出来了))

[场景 3:大脑思考,规划路线(ROS 2 & DDS)](#场景 3:大脑思考,规划路线(ROS 2 & DDS))

[场景 4:大脑指挥躯干,车轮转动(SocketCAN & CANopen)](#场景 4:大脑指挥躯干,车轮转动(SocketCAN & CANopen))

[场景 5:风险:全车断电(CoAP 极限救场)](#场景 5:风险:全车断电(CoAP 极限救场))

[三、 核心代码实战:打通"大脑"与"小脑"之间的联系](#三、 核心代码实战:打通“大脑”与“小脑”之间的联系)

[四、 总结:协议没有优劣,只有分工](#四、 总结:协议没有优劣,只有分工)


今天,我们就来做一个集大成的项目 。我们要设计并构建一款**"室外自动驾驶物流小车"**的通信架构。


在这个项目中,前 8 天学到的每一个协议(TCP/IP, HTTP, MQTT, CoAP, CAN, CANopen, ROS 2, DDS)都有它不可替代的位置。我会带你看着数据是如何在这些协议之间流转,它们是如何互补、配合,甚至是如何救命的。


假设老板给了你 500 万预算,让你带队研发一款"室外自动驾驶物流配送车"。这辆车有底盘、有雷达、要连云端、还要支持手机 APP 下单。

我们要把这 9 天学到的所有协议,全部塞进这辆车里,让它们像齿轮一样精密咬合。


一、整车通信架构全景图

首先,我们要把这辆车"解剖"成三个核心域。每个域因为任务不同,必须使用完全不同的协议。

  1. 云端交互域(互联网层): 车与手机、服务器的通信。

    • 关键词: 远程、高延迟、弱网。

    • 主角: MQTT, HTTP

  2. 高性能计算域(大脑层): 也就是你的工控机(NVIDIA Orin 或 x86 主机)。

    • 关键词: 海量数据、微秒级、进程间通信。

    • 主角: ROS 2 (DDS), TCP/UDP

  3. 实时控制域(小脑/躯干层): 也就是你的 STM32 底盘控制器。

    • 关键词: 毫秒级硬实时、电机驱动、绝对安全。

    • 主角: CAN, CANopen, micro-ROS

  4. 极限生存域(黑匣子): 独立供电的定位模块。

    • 关键词: 极低功耗、断电报警。

    • 主角: CoAP (NB-IoT)


二、 协议实战:数据的一生(从下单到车轮转动)

好,现在让我们跟踪一条指令,看它如何在这些协议之间变身、流转。

场景 1:用户下单,车辆启动(MQTT vs HTTP)

需求: 用户在手机 APP 上点了一个"开始配送"。

  • 为什么不用 HTTP?

    如果用 HTTP,车子必须每秒钟轮询服务器:"有单吗?有单吗?"这太傻了。

  • 最佳实践(MQTT):

    车辆一开机,就通过 TCP 连上云端,并 Subscribe(订阅) 主题 vehicle/1001/cmd

    用户点击按钮 -> 云端 Broker 收到请求 -> MQTT 推送 -> 车辆瞬间收到 JSON 指令

    复制代码
    {"action": "start", "target": "Gate_A"}。

    (Day 4 的知识点:这里用到了 MQTT 的 QoS 1,保证指令绝对送达,不仅快,还省流量。)

场景 2:固件有 Bug,需要紧急修复(HTTP 的优势就体现出来了)

需求: 车辆收到指令后发现版本过低,需要下载 50MB 的升级包。

  • 为什么不用 MQTT?

    MQTT 适合传短小的指令,不适合传大文件。如果用 MQTT 传 50MB,一旦中间断了一次,很难断点续传,且 Broker 压力巨大。

  • 最佳实践(HTTP):

    车辆通过 MQTT 收到一个下载链接(URL)。

    然后,车辆启动一个 HTTP GET 请求(Day 3 的知识点),去文件服务器拉取 .bin 固件。因为 HTTP 有成熟的断点续传和 CDN 加速,下载大文件稳如老狗。


场景 3:大脑思考,规划路线(ROS 2 & DDS)

需求: 固件更新完毕,车辆开始自动驾驶。激光雷达(Lidar)每秒产生 20MB 的点云数据,摄像头产生高清视频流。

  • 为什么不用 MQTT?

    数据量太大,而且都在一台电脑内部(或局域网),用 MQTT 绕一圈云端再回来,黄花菜都凉了。

  • 为什么不用 CAN?

    CAN 一帧才 8 字节,传图片?别闹了。

  • 最佳实践(ROS 2 + DDS):

    感知节点(Perception Node)发布 /lidar/points 主题。

    规划节点(Planning Node)订阅该主题。

    DDS(Day 8 的知识点) 在底层通过 Shared Memory(共享内存) 或者 UDP 组播,以几乎零拷贝的方式,瞬间把海量数据甩给规划算法。

    • QoS 配置: 雷达数据用 BestEffort(丢一帧无所谓,我要最新的);控制指令用 Reliable(必须送达)。

场景 4:大脑指挥躯干,车轮转动(SocketCAN & CANopen)

需求: 规划算法算出来了,需要左轮转速 100 RPM,右轮 120 RPM。这个指令怎么发给电机?

这里有一个极其关键的**"跨界桥梁"**。

  • 步骤 A(Linux 侧): ROS 2 节点计算出速度,通过 SocketCAN(Day 6 的知识点) 驱动,把速度数据打包成 CAN 报文。

  • 步骤 B(CAN 总线): 数据变成了差分信号,抗住电机干扰,传到底盘。

  • 步骤 C(电机侧): 伺服电机遵循 CANopen 协议(Day 7 的知识点)

    ROS 2 发来的 8 字节数据,被直接映射到电机的 对象字典 (OD) 索引 0x60FF (目标速度)。

    • 协议配合: 这里 ROS 2 负责"脑力",CAN 负责"传输",CANopen 负责"翻译"。

场景 5:风险:全车断电(CoAP 极限救场)

需求: 车子掉沟里了,主电池撞坏断电,Linux 关机,MQTT 掉线。车辆彻底失联。我们怎么找到它?

  • 最佳实践(CoAP + NB-IoT):

    车上还有一个独立的、由纽扣电池供电的黑匣子(GPS 定位器)。

    它检测到主电源断开,立刻苏醒。

    因为它电量极少,跑不起 TCP,也连不上 4G 高速网。

    它连接 NB-IoT 网络 ,通过 UDP 发送一个极其简短的 CoAP 报文(Day 5 的知识点)

    POST /alarm payload: {lat: 39.9, lon: 116.4}

    仅消耗几十字节流量,确保在电池耗尽前把位置发回服务器。


三、 核心代码实战:打通"大脑"与"小脑"之间的联系

整个系统最难的地方,在于 ROS 2 (DDS) 怎么和 CAN 总线 对话。

下面这段代码,就是 "ROS2-CAN Bridge"。它一边通过 DDS 接收 AI 的指令,一边通过 SocketCAN 指挥电机。

复制代码
#include "rclcpp/rclcpp.hpp"
#include "geometry_msgs/msg/twist.hpp" // ROS2 标准速度消息
#include <linux/can.h>
#include <linux/can/raw.h>
#include <sys/socket.h>

// 定义 CANopen 电机控制 ID
#define LEFT_MOTOR_ID 0x201
#define RIGHT_MOTOR_ID 0x202

class CanBridgeNode : public rclcpp::Node {
public:
    CanBridgeNode() : Node("can_bridge_node") {
        // 1. 初始化 SocketCAN (Day 6 知识点)
        can_socket_ = socket(PF_CAN, SOCK_RAW, CAN_RAW);
        struct ifreq ifr;
        strcpy(ifr.ifr_name, "can0");
        ioctl(can_socket_, SIOCGIFINDEX, &ifr);
        struct sockaddr_can addr;
        addr.can_family = AF_CAN;
        addr.can_ifindex = ifr.ifr_ifindex;
        bind(can_socket_, (struct sockaddr *)&addr, sizeof(addr));

        // 2. 订阅 ROS 2 的控制指令 (Day 8 知识点)
        // 只要 AI 算法发布了 /cmd_vel,这里就会收到
        sub_ = this->create_subscription<geometry_msgs::msg::Twist>(
            "/cmd_vel", 10, std::bind(&CanBridgeNode::cmd_callback, this, std::placeholders::_1));
            
        RCLCPP_INFO(this->get_logger(), "ROS2-CAN 网关已启动!");
    }

private:
    void cmd_callback(const geometry_msgs::msg::Twist::SharedPtr msg) {
        // 3. 协议转换逻辑
        // ROS 的线速度 (m/s) -> 转换为电机的转速 (RPM)
        int32_t left_rpm = (msg->linear.x - msg->angular.z * WHEEL_BASE) * RPM_RATIO;
        int32_t right_rpm = (msg->linear.x + msg->angular.z * WHEEL_BASE) * RPM_RATIO;

        // 4. 发送 CANopen PDO 报文 (Day 7 知识点)
        send_can_frame(LEFT_MOTOR_ID, left_rpm);
        send_can_frame(RIGHT_MOTOR_ID, right_rpm);
    }

    void send_can_frame(uint32_t id, int32_t rpm) {
        struct can_frame frame;
        frame.can_id = id; // CANopen 节点 ID
        frame.can_dlc = 4; // 数据长度 4 字节
        
        // 将 RPM 数据填入 CAN 报文 (小端模式)
        // 这里实际上是在通过 PDO 写入电机的 0x60FF 目标速度字典
        memcpy(frame.data, &rpm, 4);

        // 5. 写入底层 Socket (Day 2/6 知识点)
        write(can_socket_, &frame, sizeof(frame));
    }

    int can_socket_;
    rclcpp::Subscription<geometry_msgs::msg::Twist>::SharedPtr sub_;
    const float WHEEL_BASE = 0.5; // 轮距
    const float RPM_RATIO = 1000.0;
};

四、 总结:协议没有优劣,只有分工

在这 9 天的IOT学习中,我们终于把这张拼图拼完整了。

  • TCP/IP 是修路的(地基)。

  • MQTT 是跑长途物流的(连云端)。

  • HTTP 是搞大宗贸易的(下固件)。

  • CoAP 是特种兵通信(低功耗救命)。

  • ROS 2 (DDS) 是大脑内部的高速神经网络(AI 协同)。

  • CAN/CANopen 是控制肌肉的神经末梢(硬实时控制)。

真正的嵌入式/机器人架构师,不是只懂某一个协议,而是懂得在什么场景下,把最合适的协议放在最合适的位置。

这 9 天的IOT学习到此结束,但我的技术之路才刚刚开始。之后有时间准备拿着这份地图,去构建我自己的机器人!


这套架构图其实就是目前市面上主流无人车(美团、京东、百度 Apollo)的简化版通信模型。

大家觉得这个系列怎么样?如果未来我要开新的坑,你们想看 Linux 驱动开发 ,还是 RTOS 内核源码分析?评论区告诉我!

相关推荐
KaneLogger2 小时前
从传统笔记到 LLM 驱动的结构化 Wiki
人工智能·程序员·架构
斯外戈的小白2 小时前
【Agent】LangChain 1.0架构
架构·langchain
小橘子8313 小时前
(学习)Claude Code 源码架构深度解析
学习·程序人生·架构
哼?~3 小时前
Linux--网络基础
网络
FreakStudio4 小时前
小作坊 GitHub 协作闭环:fork-sync-dev-pr-merge 实战指南
python·单片机·嵌入式·面向对象·电子diy
C'ᴇsᴛ.小琳 ℡4 小时前
架构技术演进的方向
架构
刀法如飞4 小时前
Agentic Workflow 设计与实战指南
架构·agent·ai编程
苏渡苇4 小时前
Docker 网络完全指南
网络·docker·容器·docker容器·容器通信
2301_764441335 小时前
claw-code:基于Claude Code架构的clean-room重写开源项目
人工智能·架构·开源