前面几篇,我们已经把机身 Android 与 Linux 机器人主控之间的通信基本串起来了:

TCP 长连接

心跳、掉线检测与重连

粘包、半包与协议解析

Command、Ack、Timeout、Retry

Command Center 与 Command Handler

到了这里,一个新的问题出现了:

Linux 主控收到 Android 发来的指令以后,机器人到底是怎么真正动起来的?

比如 Android 发送:

OPEN_DOOR

到底是谁打开柜门?

Android 发送:

SET_LIGHT_ON

到底是谁控制灯光?

Android 发送:

GO_TO_POINT

最终又是谁让机器人的轮子真正转起来?

刚开始理解机器人架构时,很容易把整个系统画成一个简单的三级结构:

Android
   ↓ TCP
Linux 主控
   ↓ CAN / 串口
MCU
   ↓
真实硬件

这个模型没有错。但它还不够完整。

因为真实机器人里还经常存在另外一种情况:

Android
   ↓ 串口 / USB / RS485
外设 MCU / 控制板
   ↓
柜门 / 灯光 / 打印机 / 扫码器等

也就是说:

机器人内部并不是所有硬件都必须经过 Linux 主控。

真正重要的不是:

Android 能不能直接连硬件?

而是:

这个硬件能力到底应该属于哪一层?

这一篇,我们就把 Android、Linux 主控、MCU、底盘和各种外设之间的职责重新梳理清楚。


一、先把服务机器人整体架构画完整

前面我们已经明确:

服务机器人里通常存在两个上层交互端。

一个是:

机器人机身上的 Android 控制屏。

另一个是:

用户手机里的 App。

所以整个架构可以先理解成:

                   用户手机 App
                Android / iOS / KMP
                       ↓
                 HTTPS / MQTT
                       ↓
                    云端平台
                       ↓
                 MQTT / HTTPS
                       ↓
                  Linux 主控
                  ↑        ↓
                TCP     CAN / 串口
                  ↑        ↓
           机身 Android   底盘 MCU
               │           ↓
               │       电机 / 编码器
               │
        串口 / USB / RS485
               ↓
          业务外设控制板
               ↓
     柜门 / 灯光 / 打印机 / 扫码器

这张图和简单的:

Android
↓
Linux
↓
MCU

相比,多了一条非常重要的支路:

Android
↓
业务外设

所以机器人软件架构并不是一条单向流水线。

更准确地说,它是一套:

按照职责划分的多控制节点系统。


二、先区分机器人里的两个 Android

机器人项目里经常会同时出现两个 Android。

第一个是:

机器人机身 Android 控制屏

它属于机器人本体的一部分。

通常负责:

本地 UI

任务选择

地图展示

设备状态

扫码

打印

柜门操作

业务流程

运维设置

第二个是:

用户手机 App

它通常负责:

远程设备管理

远程任务

机器人状态查看

历史数据

告警

远程控制

两者最大的区别是:

机身 Android  :本地控制入口。

手机 App  :远程控制入口。

所以:

机身 Android
↓ TCP
Linux 主控

和:

手机 App
↓ Cloud
↓
Linux 主控

是两条不同的控制链路。

但是它们最后都会进入:

机器人真正的能力层。


三、Android 的核心职责仍然是业务与交互

虽然 Android 可以直接串口控制某些硬件,但这并不改变 Android 最主要的角色。

Android 仍然主要负责:

业务与人机交互。

例如用户在机器人屏幕点击:

前往会议室

Android 应该表达:

GO_TO_POINT
pointId = meeting_room

而不是:

左轮 PWM = 120
右轮 PWM = 115

用户点击:

开始巡航

Android 应该表达:

START_PATROL

而不是直接控制电机。

因为:

去哪里
开始什么任务
执行什么业务

属于业务语义。

而:

轮子怎么转
导航怎么规划
如何避障

属于机器人核心控制能力。

所以对于:

  • 导航
  • 底盘
  • 定位
  • 任务
  • 回充

这类能力,Android 更应该调用 Linux 主控提供的:

机器人能力接口。


四、Linux 主控负责机器人核心能力

Linux 主控通常是整台机器人的核心控制节点。

它可能负责:

任务状态机

SLAM

定位

导航

路径规划

底盘控制

核心传感器

回充

设备状态

机器人安全状态

云端通信

例如 Android 发送:

GO_TO_POINT
pointId = 10

Linux 主控可能需要:

读取目标点位

↓

检查地图

↓

检查当前定位

↓

启动导航

↓

规划路径

↓

持续获取 Pose

↓

输出运动目标

↓

控制底盘

↓

监测导航结果

最后再向 Android 返回:

NAVIGATION_START

↓

NAVIGATING

↓

ARRIVED

所以可以简单理解:

Android
负责:
用户想让机器人做什么

Linux 主控
负责:
机器人如何完成这件事

五、MCU 又负责什么?

再往下,就是 MCU。

例如:

STM32 或者 其他单片机。

MCU 和 Linux 擅长的事情并不一样。

Linux 更擅长:

复杂业务

网络

任务调度

导航

算法

文件系统

多线程

MCU 更擅长:

实时控制

GPIO

PWM

电机

编码器

传感器采集

硬件时序

低级总线通信

所以可以理解成:

Linux
决定:
机器人应该怎么做

↓

MCU
负责:
让硬件真正按照要求执行

六、底盘就是一个典型的 MCU 控制子系统

机器人底盘通常包含:

底盘控制器

MCU

电机驱动

编码器

IMU

轮子

急停

电源系统

典型结构:

Linux 主控
    ↓ CAN / 串口
底盘控制器
    ↓
电机驱动
    ↓
电机 / 轮子

Linux 可能发送的是:

linearVelocity = 0.5 m/s

angularVelocity = 0.2 rad/s

而不是:

左轮 PWM = 123
右轮 PWM = 118

底盘 MCU 再根据目标速度处理:

左右轮速度

PID

编码器反馈

电机控制

所以传统意义上的底盘更像:

机器人的运动执行子系统。


七、底盘通常不会直接和云端通信

对于传统底盘来说:

底盘 MCU

通常不会直接:

MQTT
↓
Cloud

真正连接云端的通常是:

Linux 主控

所以远程控制可能是:

手机 App
    ↓
Cloud
    ↓
Linux 主控
    ↓
导航 / 任务
    ↓
底盘控制器
    ↓
电机

例如手机发起:

RETURN_TO_CHARGE

并不是:

Cloud
↓
直接控制电机

而是:

Cloud
↓
Linux 主控
↓
创建回充任务
↓
导航系统
↓
底盘运动

所以:

云端负责远程业务与任务。

Linux 主控负责机器人核心控制。

底盘负责运动执行。


八、为什么有些“底盘”看起来又像 Linux 设备?

现在很多厂商卖的并不是简单底盘。

而是:智能底盘

里面可能已经集成:

ARM / 工控机

Linux

ROS / ROS2

SLAM

Navigation

雷达

底盘 MCU

电机

这时候外部开发者看到的可能就是:

Android
    ↓ TCP / API
智能底盘

于是很容易产生一种感觉:

底盘是不是其实就是一个 Linux 服务?

更准确地说:

不是底盘 MCU 变成了 Linux,而是厂商把 Linux 主控和传统底盘一起封装成了“智能底盘产品”。

传统结构:

Linux 主控
    ↓
底盘 MCU
    ↓
电机

被厂家封装以后:

智能底盘

所以以后看到“底盘”这个词,最好先判断:

它只是运动控制器,还是已经包含 Linux 主控?

这是两个完全不同的东西。


九、但机器人内部并不是所有硬件都要经过 Linux

前面这些内容容易给人一个感觉:

Android
↓
Linux
↓
MCU
↓
所有硬件

真实机器人往往并不是这样。

Android 本身也可能通过:

UART

USB Serial

RS485

USB

GPIO

直接连接一些业务外设。

例如:

Android
   ↓ 串口
柜门控制板

或者:

Android
   ↓ USB
扫码器

或者:

Android
   ↓ USB
打印机

甚至:

Android
   ↓ RS485
灯光 / 托盘控制器

这些设计完全合理。


十、为什么 Android 可以直接控制这些外设?

因为这些设备和 Android 上层业务流程 往往绑定得非常紧。

例如云柜机器人:

用户扫码

↓

Android 获取扫码结果

↓

校验业务

↓

打开柜门

↓

页面提示取货

↓

关闭柜门

↓

业务结束

如果柜门控制板本身就直接连接 Android:

Android
↓ Serial
柜门 MCU

那么没必要为了“架构漂亮”强行绕成:

Android
↓ TCP
Linux
↓ Serial
柜门 MCU

后者反而增加了:

  • 通信链路
  • 依赖关系
  • 故障点
  • 处理延迟

所以:

分层不是为了多加一层。

分层真正的目的是:

让能力归属合理。


十一、什么硬件更适合 Linux 主控?

一般来说,如果这个能力属于:

机器人核心运动与自主运行能力

更适合 Linux 主控统一管理。

例如:

底盘

导航

定位

SLAM

避障

核心雷达

回充

核心运动传感器

安全控制

因为即使:

  • Android App 崩溃
  • Android 页面切换
  • Android UI 卡住

机器人核心运动能力仍然应该继续正常运行。

例如机器人正在自主巡航:

Android App 崩溃

不应该导致:

底盘立即失控

所以:

机器人核心控制能力不能依赖 UI 进程存在。


十二、什么硬件可以直接属于 Android?

与 HMI 和业务交互 关系更强的设备,则完全可以由 Android 直接管理。

例如:

扫码器

读卡器

打印机

部分柜门

灯带

业务按钮

USB 摄像头

某些托盘控制器

身份证阅读器

这些硬件本身就是:

Android 业务终端的一部分。

例如:

扫码
↓
业务校验
↓
开柜
↓
打印凭证

整条业务都发生在 Android 上。

这时候让 Android 直接控制对应外设,反而最自然。


十三、所以应该把机器人硬件分成两类

可以先做一个简单抽象:

                    机器人硬件
                         │
          ┌──────────────┴──────────────┐
          │                             │
     核心机器人能力                 业务交互外设
          │                             │
      Linux 主控                      Android
          │                             │
     CAN / 串口                    串口 / USB
          │                             │
         MCU                           MCU
          │                             │
  底盘 / 电机 / 核心传感器      柜门 / 打印 / 扫码等

这里并不存在绝对规定。

真正要判断的是:

这个能力到底属于机器人核心运行,还是属于 Android 业务交互?


十四、Android 直接串口控制硬件,不等于 ViewModel 直接写串口

例如 :Android 控制柜门。

最简单的代码可能是:

ViewModel
    ↓
serialPort.write(
    AA 10 03 01 ...
)

短期看起来很方便。

但是这样意味着,ViewModel 已经知道:

串口协议

包头

Command

柜门编号

Checksum

这实际上又把:

业务层  和  硬件协议层 混在了一起。

所以即使 Android 直接控制硬件:

仍然应该分层。


十五、Android 直接控制外设时,也应该有 Hardware Adapter

例如柜门可以这样设计:

UI
 ↓
ViewModel
 ↓
DoorRepository
 ↓
DoorController
 ↓
DoorHardwareAdapter
 ↓
SerialPort
 ↓
柜门 MCU

业务层只知道:

openDoor(3)

而:

DoorHardwareAdapter

才知道真正协议:

AA 10 03 01 FF XX

这样以后:

  1. 串口协议变化
  2. 柜门板更换
  3. 设备厂家变化

只需要修改:

DoorHardwareAdapter

上层业务基本不用动。


十六、所以“业务协议与硬件协议分离”仍然成立

之前我说 ,Android 不应该知道 MCU 的:

AA 10 03 01 ...

这个结论仍然成立。

但需要把表达修正为:

不是 Android 不能直接控制 MCU,而是 Android 的业务层不应该直接依赖 MCU 协议。

例如下面这种完全合理:

ViewModel
↓
DoorController.openDoor(3)
↓
DoorSerialAdapter
↓
SerialPort
↓
MCU

因为:

业务层

仍然不知道:

硬件协议细节

这才是关键。


十七、Linux 这一侧也是同样的思想

Linux 主控控制底盘也一样。

业务层不应该直接:

sendCanFrame(...)

更合理的是:

Navigation
    ↓
ChassisController
    ↓
ChassisHardwareAdapter
    ↓
CAN
    ↓
底盘 MCU

导航模块只关心:

setVelocity(v, w)

而:

ChassisHardwareAdapter

负责转换成具体: CAN Frame。

所以无论硬件接在: Android 还是  Linux

架构思想其实完全一样:

业务能力
↓
Controller
↓
Hardware Adapter
↓
具体协议
↓
真实硬件

十八、一个机器人里可能同时存在两套硬件控制链路

这才是非常真实的一种机器人架构。

例如:

                    Linux 主控
                   /          \
                  /            \
             底盘控制        核心传感器
            CAN / Serial     CAN / Serial
                ↓                ↓
              MCU              MCU
                ↓                ↓
          电机 / 编码器       雷达等


机身 Android
       │
       ├── TCP ─────────────→ Linux 主控
       │
       ├── Serial ──────────→ 柜门控制板
       │
       ├── USB ─────────────→ 扫码器
       │
       └── USB ─────────────→ 打印机

这并不代表架构混乱。

只要:

职责划分清楚。

就完全没有问题。


十九、一个“打开柜门”可能有两种实现

例如第一种机器人:

柜门属于 Linux 管理。

那么:

Android
↓ TCP
Linux
↓ Serial
柜门 MCU

Android 调用:

OPEN_DOOR

Linux 再执行。


另外一种机器人:

柜门控制板直接接 Android。

那么:

Android
↓ Serial
柜门 MCU

Android 业务层调用:

doorController.openDoor(3)

最终由:

DoorSerialAdapter

生成硬件协议。

两种方案都可以。

关键要看:

柜门能力属于谁?

谁掌握业务状态?

谁需要在 Android 离线时继续控制它?

这个能力是否被其他控制入口共享?

这些问题决定:

它应该挂在哪一层。


二十、如果多个入口都需要控制这个硬件怎么办?

这时候能力归属就更重要了。

假设柜门不仅:

机身 Android

需要控制。

手机 App 也需要:

远程开门。

机器人自主流程也可能需要:

自动开门。

如果柜门只存在:

Android → Serial

那远程控制就必须:

手机 App
↓
Cloud
↓
Linux
↓
Android
↓
Serial
↓
柜门

系统可能开始复杂。

这种情况下就需要重新考虑:

柜门是不是应该成为机器人主控统一能力?

因此是否让 Android 直接控制,并没有绝对答案。

一个很实用的判断方式是:

谁应该成为这个硬件能力的事实拥有者?

如果它主要属于 Android 本地业务:

放 Android。

如果它属于机器人全局能力,并且多个入口都需要使用:

放 Linux 主控通常更合适。


二十一、所以分层真正依据的不是“谁能连接硬件”

Android 技术上可以:

串口。

Linux 当然也可以:

串口。

所以不能简单地说:

能连接
=
应该归它管理

真正应该看:

能力归属

生命周期

实时性

安全性

多入口复用

故障隔离

是否需要脱离 Android 独立运行

例如:

底盘:

即使 Android 挂了也要安全工作。

所以更适合 Linux + MCU。

打印机:

主要服务 Android 页面业务。

所以直接由 Android 控制很合理。

这才是真正的架构判断。


二十二、再看手机 App,它永远不应该直接知道底层协议

用户手机 App 距离机器人更远。

通常是:

手机 App
↓
Cloud
↓
Linux

它更不应该知道:

CAN

UART

GPIO

MCU Command

手机只应该表达:

START_TASK

OPEN_DOOR

RETURN_TO_CHARGE

甚至再往上:

创建巡航任务

开始配送任务

越往系统外层:业务语义应该越高。

越往硬件底层:协议和控制细节才越来越具体。


二十三、机器人软件其实是一组不同层级的能力

做到这里,可以把整个机器人理解成:

用户业务层
手机 App / 机身 Android UI

↓

机器人业务能力
任务 / 巡航 / 开门 / 回充

↓

核心控制能力
Linux 主控 / Navigation / Chassis

↓

硬件能力
Controller / Hardware Adapter

↓

通信协议
TCP / CAN / Serial / RS485 / USB

↓

设备
MCU / 电机 / 传感器 / 外设

但是:

这些层级是逻辑层级,不代表物理连接一定是一条直线。

例如:

Android UI
↓
DoorController
↓
Serial
↓
柜门

完全可以绕过 Linux。

而:

Android UI
↓ TCP
Linux
↓
Navigation
↓ CAN
底盘

也完全合理。

这就是:

逻辑分层和物理拓扑不是一回事。


二十四、这是这一篇最重要的修正

如果只用一句话总结:

不是:

Android → Linux → MCU → 硬件,所有指令都必须逐级向下。

而应该是:

Android、Linux 和 MCU 按职责分层,不同硬件根据能力归属连接到最合适的控制节点。

例如:

机器人核心能力
→ Linux

业务交互能力
→ Android

实时硬件执行
→ MCU

而:

Hardware Adapter

负责隔离具体硬件差异。

这样理解以后,机器人真实项目中的各种硬件拓扑就不会显得矛盾了。


二十五、Android、Linux、MCU 可以这样记

Android

主要负责:

  1. 业务与人机交互。
  2. 同时可以直接管理 与 Android 业务强相关的局部外设。

例如:

扫码器

打印机

读卡器

部分柜门

部分灯光

Linux 主控

负责:

机器人核心能力与全局协调。

例如:

任务

导航

SLAM

定位

底盘

回充

核心设备状态

云端通信

MCU

负责:

实时硬件执行。

例如:

电机

编码器

GPIO

传感器

锁控

执行机构

所以不是:

Android
↓
Linux
↓
MCU

这么简单。

更准确的是:

                 Linux
           机器人核心能力
            ↓          ↓
          MCU         MCU
           ↓           ↓
         底盘       核心硬件


Android
业务与交互
   │
   ├── TCP → Linux
   │
   └── Serial / USB → 业务外设

二十六、一个成熟机器人架构真正要做到什么?

最后再往架构层抽象一步。

真正重要的不是:

硬件到底接 Android 还是 Linux

而是做到:

第一,能力归属清楚

谁负责这个能力?Android?Linux 还是 MCU?


第二,业务和协议解耦

业务调用:

openDoor()

而不是:

write(AA 10 03 ...)

第三,硬件变化被隔离

例如:

DoorHardwareAdapterV1

↓

DoorHardwareAdapterV2

而不是整个业务一起修改。


第四,核心机器人能力不依赖 UI

Android 崩溃:

机器人底盘、导航、安全控制仍然能够维持正确状态。


第五,多入口控制时有统一能力归属

机身 Android

手机 App

云端

自主任务

都可能调用同一个机器人能力。

不能每一个入口都各自实现一套硬件控制。


二十七、总结

这一篇最重要的不是记住一张:

Android
↓
Linux
↓
MCU

的图。

而是理解机器人真正的分层原则:

按能力和职责分层,而不是简单按物理连接分层。

机器人核心链路通常是:

机身 Android
      ↓ TCP
Linux 主控
      ↓ CAN / 串口
底盘 MCU
      ↓
电机 / 编码器

但同时也完全可能存在:

机身 Android
      ↓ Serial / USB / RS485
业务外设 MCU
      ↓
柜门 / 打印机 / 扫码器 / 灯光

所以:

Android 可以直接串口控制硬件。

关键不是:

Android 能不能控制。

而是:

这个能力应该归谁负责?

同时,无论硬件最终连接 Android 还是 Linux,都应该坚持:

业务能力

↓

Controller

↓

Hardware Adapter

↓

硬件协议

↓

真实设备

避免:

ViewModel
↓
直接拼 ByteArray
↓
写串口 / CAN

因此一个更加准确的服务机器人架构是:

                    手机 App
                       ↓
                     Cloud
                       ↓
                  Linux 主控
                  ↑        ↓
                TCP      CAN / Serial
                  ↑        ↓
           机身 Android   核心 MCU
               │            ↓
               │         底盘等
               │
        Serial / USB
               ↓
          业务外设 MCU
               ↓
      柜门 / 打印 / 扫码等

做到这里,我们已经不再只是讨论:Android 怎么控制硬件。

而是在回答一个更本质的问题:

一台机器人里的不同能力,应该由谁拥有、谁执行、谁对最终状态负责?

而一旦机器人同时存在:

  • 机身 Android
  • 手机 App
  • 云端后台
  • 自主任务
  • 维护人员

这些入口,下一个问题马上就来了:

多个入口同时想控制机器人时,到底听谁的?

下一篇:第 7 篇

《服务机器人如何处理多种控制入口:LOCAL、REMOTE、AUTO 与安全优先级》

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐