7-fix补充篇:机器人为什么需要多级控制仲裁?Cloud、Linux 与 MCU 分别管什么
上一篇,我们讨论了服务机器人为什么会存在多个控制入口。
例如:
机身 Android
手机 App
Cloud
AUTO Task
Maintenance
这些入口最终可能都会要求机器人:
开始任务
停止任务
前往某个点位
返回充电
打开柜门
所以机器人不能简单采用:
谁最后发送 Command
就执行谁
而需要:
Control Arbiter
也就是:
控制权仲裁。
但是继续往下分析以后,又会出现一个新的问题。
手机远程控制机器人时,本身就要经过 Cloud:
手机 App
↓
Cloud
↓
Robot
那么 Cloud 要不要做一次控制权仲裁?
如果 Cloud 已经判断:
ALLOW
机器人本地为什么还要再判断一次?
再往下:
Linux 主控已经允许执行,
为什么 MCU 还可能拒绝电机动作?
也就是说:
为什么一条机器人指令,可能要经过不止一次“允许 / 拒绝”判断?
这一篇,我们就把这个问题彻底拆开。
一、先看一个最简单的远程控制场景
假设用户在手机 App 上点击:
RETURN_TO_CHARGE
控制链路:
手机 App
↓
Cloud
↓ MQTT
机器人 Linux 主控
↓
Navigation
↓
Chassis
↓
MCU
↓
Motor
表面上看,这似乎只是一条:
RETURN_TO_CHARGE
指令。
但真正执行过程中,至少会遇到三个完全不同的问题。
第一个问题:
这个用户有没有资格让这台机器人回充?
第二个问题:
机器人当前状态允不允许执行回充?
第三个问题:
底盘当前物理状态允不允许移动?
这三个问题显然不是一个层级的问题。
所以:
Control Arbitration
天然就会出现分层。
二、可以把它先抽象成三级
一个比较完整的机器人控制体系可以理解成:
第一级
Cloud Global Arbiter
“业务上能不能下发?”
↓
第二级
Robot / Linux Arbiter
“机器人现在能不能执行?”
↓
第三级
MCU Safety Interlock
“物理上能不能安全执行?”
↓
Hardware
这三层看起来都在做:
ALLOW / REJECT
但是它们检查的条件完全不同。
所以:
这不是重复判断,而是分层防线。
三、第一级:Cloud Control Arbiter
先看 Cloud。
手机 App 发起:
RETURN_TO_CHARGE
Cloud 首先掌握的是:
全局业务信息。
例如:
当前用户是谁?
机器人属于谁?
这个用户有没有控制权限?
当前是否已经有人在远程控制?
当前是不是已经存在冲突任务?
是不是另一个 App 已经获得控制权?
设备是否在线?
远程控制租约是否有效?
这些信息最适合谁判断?
当然是:
Cloud
因为机器人本地通常根本不知道:
这个用户的账号权限。
四、Cloud 仲裁解决的是“全局业务问题”
例如用户 A 和用户 B 同时打开 App。
用户 A:
START_TASK
用户 B:
RETURN_TO_CHARGE
机器人本地可能只看到:
Command A
Command B
但 Cloud 知道:
User A
=
设备管理员
User B
=
普通查看用户
所以 Cloud 可以直接:
User A
→ ALLOW
User B
→ REJECT
机器人根本不需要收到用户 B 的控制指令。
这就是 Cloud Arbiter 的价值。
五、Cloud 还可以管理“远程控制权”
假设一个服务机器人支持远程人工控制。
用户 A 已经获得:
REMOTE CONTROL
此时用户 B 又尝试接管。
Cloud 可以维护:
Control Owner
例如:
owner = userA
mode = REMOTE
leaseId = abc123
用户 B 请求:
TAKE_CONTROL
Cloud 判断:
当前已有远程控制者
于是:
REJECT
reason = REMOTE_CONTROL_OCCUPIED
这种:
多用户
多 App
账号权限
控制租约
问题显然非常适合在云端解决。
六、为什么可能还需要 Control Lease?
假设用户 A 获得了远程控制权。
然后:
手机断网
Cloud 不能永久认为:
userA
还在控制机器人。
所以可以设计:
Control Lease
例如:
owner = userA
expiresAt = 10s later
客户端需要持续:
renew
如果长时间没有续约:
Control Lease Expired
Cloud 就可以释放:
REMOTE CONTROL
这和分布式系统中的:
Lease
思想非常接近。
七、Cloud ALLOW 到底意味着什么?
这里一定要建立一个重要认知。
Cloud 返回:
ALLOW
并不代表:
机器人必须执行。
它真正表示的是:
从云端当前掌握的全局业务状态来看,这条指令允许被下发。
也就是:
Cloud ALLOW
=
允许发送给 Robot
而不是:
Cloud ALLOW
=
Robot 必须执行
这两个概念完全不同。
八、为什么 Robot 还必须再做一次仲裁?
因为 Cloud 不掌握机器人此刻最真实的本地状态。
例如 Cloud 当前记录:
mode = REMOTE
state = IDLE
于是允许:
RETURN_TO_CHARGE
但是就在几百毫秒前,
现场用户通过机身 Android:
切换 LOCAL
Linux 当前真实状态已经变成:
mode = LOCAL
只是最新状态还没有来得及同步到 Cloud。
这时候如果机器人完全相信 Cloud:
Cloud ALLOW
↓
直接执行
远程命令就可能和现场控制发生冲突。
所以机器人本地必须:
重新判断一次。
九、第二级:Robot / Linux Control Arbiter
对于服务机器人来说,真正的本地控制入口可能是:
Cloud
│
│
机身 Android ──────┼──→ Linux
│
AUTO Task ─────────┤
│
Maintenance ───────┘
这几个入口最终真正汇聚的位置是:
Linux 主控
所以 Linux 这一层应该知道:
当前 ControlMode
当前 ControlOwner
当前任务
当前 Navigation 状态
当前是否 Maintenance
当前是否有人 Local 接管
当前机器人实际运行状态
因此:
机器人本地 Control Arbiter 通常应该靠近 Linux 主控。
十、Linux Arbiter 判断的不是“这个用户是谁”
例如远程收到:
RETURN_TO_CHARGE
Linux 通常没有必要重新判断:
这个用户是不是 VIP?
账号是否过期?
设备是不是属于这个用户?
这些 Cloud 已经处理。
Linux 真正关心的是:
当前是不是 LOCAL?
机器人是不是正在 MAINTENANCE?
当前 AUTO Task 能不能被打断?
机器人是不是正在执行另一项高优先级任务?
当前 Navigation 是否允许启动新目标?
当前状态是不是 CHARGING?
是不是已经处于 RETURNING?
这些属于:
本地机器人状态。
十一、服务机器人为什么尤其依赖本地仲裁?
因为它有一个非常重要的入口:
机身 Android
↓ TCP
Linux
这条链路:
根本不经过 Cloud。
例如:
手机 App
↓
Cloud
↓
RETURN_TO_CHARGE
Cloud 判断:
ALLOW
但与此同时,
现场用户:
机身 Android
↓
STOP_TASK
甚至:
切换到 LOCAL
Cloud 很可能还不知道这件事情。
但是 Linux 知道。
所以:
Linux Control Arbiter
必须成为:
机器人本地控制状态的最终事实源。
十二、一个服务机器人指令可以这样走
例如手机远程点击:
RETURN_TO_CHARGE
第一步:
手机 App
↓
Cloud
Cloud 判断:
用户权限 ✓
设备归属 ✓
远程控制权 ✓
任务冲突 ✓
于是:
Cloud Arbiter
→ ALLOW
然后:
Cloud Command Center
↓ MQTT
Linux
Linux 收到以后:
Command Handler
先解析:
RETURN_TO_CHARGE
然后进入:
Robot Control Arbiter
继续判断:
currentMode = ?
controlOwner = ?
currentTask = ?
robotState = ?
navigationState = ?
假设发现:
currentMode = LOCAL
那么:
Robot Arbiter
→ REJECT
返回:
reason = LOCAL_CONTROL_ACTIVE
这是完全正常的。
十三、所以 Cloud ALLOW + Robot REJECT 并不矛盾
因为两边回答的问题不同。
Cloud:
这个远程请求
从全局业务角度
允许发送
Robot:
但从机器人此刻真实状态来看
现在不能执行
所以:
Cloud = ALLOW
Robot = REJECT
完全可能。
甚至是一个成熟系统必须允许出现的情况。
十四、那 Linux ALLOW 以后是不是就一定执行?
仍然不一定。
因为下面还有:
MCU
以及:
真实硬件。
假设 Linux 判断:
当前 REMOTE
没有任务冲突
Navigation 正常
允许回充
于是:
Robot Arbiter
→ ALLOW
然后 Navigation 开始控制底盘:
linearVelocity = 0.5m/s
但就在此刻,底盘检测到:
急停按下
怎么办?
当然还是不能动。
十五、第三级:MCU Safety Interlock
这里我更愿意叫:
Safety Interlock
而不是继续全部叫:
Control Arbiter
因为 MCU 做的已经不是:业务控制权仲裁。
而是:实时物理安全保护。
它可能检查:
Emergency Stop
Bumper
Cliff Sensor
Motor Overcurrent
Driver Fault
Watchdog
Communication Lost
Temperature
Hardware Limit
如果任何一个条件触发:
BLOCK
即使 Linux 发:
MOVE_FORWARD
MCU 仍然:
拒绝执行
甚至直接:
切断电机输出
十六、为什么 Safety 不能只放 Linux?
因为 Linux 本身也可能:
卡死
线程阻塞
进程崩溃
通信异常
系统负载过高
如果安全保护完全依赖:
Linux
那么 Linux 出问题时:安全能力也跟着失效。
所以一些关键保护需要继续下沉到:
MCU
Safety Controller
甚至纯硬件电路
例如物理急停可以设计成:
急停按钮
↓
Safety Circuit / MCU
↓
Motor Driver
直接阻止电机输出。
它不应该要求:
Android
↓ TCP
Linux
↓ CAN
MCU
完整链路正常以后才能停车。
十七、所以 STOP_TASK 和 Emergency Stop 属于不同层
例如:
STOP_TASK
属于业务控制。
可能经过:
Command Center
↓
Control Arbiter
↓
Task Manager
↓
Navigation
↓
平滑停止
它会考虑:
任务状态
业务结果
云端同步
而:
EMERGENCY STOP
关注的是:
先让危险动作停下来
它甚至可以绕开:
Task Manager
直接作用到:
Chassis / Motor
因此:
STOP_TASK ≠ EMERGENCY_STOP
一个是:业务停止。
一个是:安全停止。
十八、现在再看割草机器人
割草机器人也存在控制仲裁。
只是它和服务机器人控制入口分布不同。
割草机器人更常见的是:
手机 App
↓
Cloud
↓
Mower
远程业务入口首先汇聚到:
Cloud
所以 Cloud 可以承担很大一部分:
Global Control Arbiter
例如:
用户权限
设备归属
远程控制权
计划任务冲突
手动任务和自动任务冲突
多客户端操作
然后:
Cloud
↓ MQTT
Mower
十九、割草机器人本地为什么仍然需要判断?
例如 Cloud 下发:
START_MOWING
云端认为:
用户权限 ✓
设备在线 ✓
当前没有任务冲突 ✓
但是割草机器人此刻发现:
RTK / 定位不可用
电池过低
刀盘故障
机器人倾倒
急停按下
驱动故障
那么机器人仍然必须:
REJECT
例如:
reason = POSITIONING_NOT_READY
或者:
reason = LOW_BATTERY
所以割草机器人也是:
Cloud Global Arbiter
↓
Robot Local Check
↓
Safety
↓
Execution
只是:云端仲裁承担的比例更大。
二十、服务机器人和割草机器人真正的差异在哪?
放在一起就很清楚。
割草机器人
App A ─┐
│
App B ─┼→ Cloud
│ Global Arbiter
计划任务┘
↓
MQTT
↓
Robot
Local / Safety
↓
Chassis
它的特点:
大多数外部业务控制首先汇聚 Cloud。
服务机器人
手机 App
↓
Cloud ───────────┐
│
机身 Android ──────┼→ Linux
│ Local Arbiter
AUTO Task ─────────┤
│
Maintenance ───────┘
↓
MCU Safety
它的特点是:
存在机身 Android → TCP → Linux 这条绕过 Cloud 的本地控制链路。
所以:
Linux Local Arbiter
在服务机器人里会更加重要。
二十一、这也解释了为什么服务机器人的控制体系更复杂
割草机器人大量控制入口可以先:
Cloud
统一。
而服务机器人同时存在:
LOCAL
REMOTE
AUTO
MAINTENANCE
并且很多入口:直接发生在机器人本体。
所以 Linux 必须统一处理:
谁现在拥有控制权?
哪一种 Mode?
哪一个 Source?
哪一种 Command?
能不能抢占当前任务?
因此服务机器人会更明显地出现:
Robot Control Arbiter
这个独立架构角色。
二十二、这里还需要区分“普通底盘”和“智能底盘”
我们前面一直说:
Linux Arbiter
但实际项目中,有时候大家会说:
控制仲裁在底盘。
这句话是不是错?
不一定。
如果所谓的:
智能底盘
内部已经包含:
Linux
ROS / ROS2
Navigation
底盘服务
MCU
那么完全可以理解成:
Android
↓ TCP
智能底盘 Linux
【Control Arbiter】
↓
底盘 MCU
所以工程上说:
控制权仲裁在底盘
没有问题。
但是如果所谓底盘只是:
STM32
Motor Driver
Encoder
Wheel
那么更准确应该是:
Linux 主控
【业务 Control Arbiter】
↓
底盘 MCU
【Safety Interlock】
普通 MCU 一般不应该负责:
LOCAL 和 REMOTE 谁优先?
手机用户有没有远程控制权限?
AUTO Task 能不能被 App 抢占?
这些属于上层业务逻辑。
二十三、Cloud Arbiter 和 Command Center 也不是一回事
前面的补充篇我们讲过:
Command Center
它负责:
CommandId
Pending
Timeout
Retry
Result
Command Lifecycle
而:
Control Arbiter
负责:
这条 Command 有没有资格继续向下执行?
所以 Cloud 里可能同时有:
Cloud
├── Command Center
│ ↓
│ 管 Command 生命周期
│
└── Control Arbiter
↓
管远程业务控制权
两者可能属于同一个服务实现。
也可能以后拆成不同模块。
但逻辑职责要分开。
二十四、Robot 端也是一样
机器人 Linux:
MQTT / TCP
↓
Command Handler
↓
Control Arbiter
↓
Task / Navigation / Device
Command Handler 负责:
解析
校验
去重
幂等
Control Arbiter 负责:
当前是否允许执行
Task / Navigation 负责:
真正完成机器人能力
所以一个完整链路可以变成:
Command Center
↓
Communication
↓
Command Handler
↓
Control Arbiter
↓
Capability
↓
Hardware Adapter
↓
MCU Safety
↓
Hardware
这时候前几篇内容就全部串起来了。
二十五、三级系统各自掌握什么“事实”?
这是理解多级仲裁最好用的方法。
Cloud
掌握:
全局业务事实。
例如:
用户是谁
设备属于谁
远程控制者是谁
任务历史
账号权限
远程 Lease
Robot / Linux
掌握:
当前机器人执行事实。
例如:
当前 ControlMode
当前 Task
当前 Navigation
当前 Local 控制者
是否 Maintenance
设备当前真实运行状态
MCU / Safety
掌握:
当前物理事实。
例如:
急停有没有按下
电机有没有过流
碰撞有没有触发
驱动器是否故障
硬件是否允许输出
所以可以记成:
Cloud
全局业务事实
↓
Robot
本地执行事实
↓
MCU
物理安全事实
谁最接近事实,谁负责这一层最终判断。
二十六、这也是为什么状态不能只相信 Cloud
假设 Cloud 显示:
Robot = IDLE
并不代表机器人此刻一定还是:
IDLE
因为状态同步存在:
网络延迟
MQTT 延迟
数据库更新延迟
消息顺序
Robot 本地状态永远更加接近:
当前真实执行情况。
同样:
Linux 认为:
Motor = READY
也不代表下一毫秒电机一定能运行。
MCU 可能刚刚检测:
OVER_CURRENT
所以机器人控制必须接受:
越接近硬件,状态越实时。
二十七、最终执行原则:越往下越有否决权
这个模型还可以总结出一个非常重要的设计原则:
Cloud 可以允许
Robot 可以否决
MCU 还可以继续否决
也就是:
Cloud ALLOW
↓
Robot ALLOW
↓
MCU ALLOW
↓
Execute
任何一层:
REJECT
最终都不能执行。
例如:
Cloud
ALLOW
↓
Linux
ALLOW
↓
MCU
REJECT
急停触发
最终:
机器人不移动
不能因为 Cloud 已经允许,
就强制绕过下面的安全系统。
所以:
上层拥有调度权,下层拥有基于真实状态的否决权。
这个原则非常重要。
二十八、但下层不能反过来越权做上层业务决策
同样需要注意另外一面。
MCU 有权因为:
Emergency Stop
拒绝运动。
但是 MCU 不应该自己判断:
User A
比 User B 权限高
Robot Linux 可以判断:
当前 LOCAL
所以拒绝 REMOTE
但它通常不需要维护整个:
用户会员体系
账号权限
组织结构
所以好的分层不是:
大家什么都判断一遍。
而是:
每一层只判断自己最了解的事实。
二十九、把一个远程回充完整走一遍
用户:
RETURN_TO_CHARGE
第一层:
手机 App
↓
Cloud
Cloud Arbiter:
用户权限?
✓
设备归属?
✓
远程控制权?
✓
业务任务冲突?
✓
↓
ALLOW
Command Center:
创建 commandId = 1001
然后:
MQTT
↓
Robot
Robot Command Handler:
解析
去重
校验
进入 Robot Control Arbiter:
LOCAL 是否正在控制?
否
MAINTENANCE?
否
当前任务允许中断?
是
当前 RobotState 允许回充?
是
↓
ALLOW
进入:
Navigation
产生底盘控制:
setVelocity(...)
MCU Safety:
EmergencyStop?
否
Bumper?
否
DriverFault?
否
Watchdog?
正常
↓
ALLOW
最后:
Motor Execute
这才是一条完整的机器人控制链路。
三十、如果中途被拒绝怎么办?
假设 Cloud:
ALLOW
但是 Robot:
REJECT
reason = LOCAL_CONTROL_ACTIVE
机器人应该把结果上报:
commandId = 1001
status = REJECTED
reason = LOCAL_CONTROL_ACTIVE
Cloud Command Center 更新:
1001
REJECTED
手机 App 最终显示:
机器人当前正在本地控制
暂时无法远程回充
这时候用户看到的是:
业务拒绝。
而不是:
请求失败
或者:
网络异常
这就是前面 Command / Result 设计继续发挥作用的地方。
三十一、多级仲裁其实和前面所有文章都连起来了
回头看第二季前面几篇:
TCP 长连接解决:
Android 和 Linux 怎么长期通信?
粘包半包解决:
TCP 字节流怎么还原消息?
Command / Ack / Retry 解决:
指令怎么可靠执行?
Command Center 解决:
谁管理指令生命周期?
Android / Linux / MCU 分层解决:
能力应该属于谁?
多控制入口解决:
Command 可能从哪里来?
而这一篇的多级仲裁解决:
这么多 Command
到底哪些有资格继续向下执行?
整个体系开始完整起来。
三十二、最终可以得到一张机器人控制架构图
手机 App / 管理后台
↓
┌───────────────┐
│ Cloud │
│ │
│ Control │
│ Arbiter │
│ │
│ Command │
│ Center │
└───────┬───────┘
│
MQTT
↓
┌─────────────────┐
│ Robot / Linux │
│ │
TCP ───→│ Command Handler │
↑ │ │
│ │ Control Arbiter │
│ │ │
│ │ Task / Nav │
│ └────────┬────────┘
│ │
│ CAN / Serial
│ ↓
│ ┌─────────────────┐
│ │ MCU / Safety │
│ │ │
│ │ E-Stop │
│ │ Bumper │
│ │ Overcurrent │
│ │ Watchdog │
│ └────────┬────────┘
│ ↓
│ Hardware
│
机身 Android
从上到下分别回答:
Cloud
业务上能不能下发?
↓
Linux
机器人现在能不能执行?
↓
MCU
物理上能不能安全执行?
三十三、总结
机器人里的:
Control Arbiter
并不一定只有一个。
对于复杂机器人系统,很自然会形成:
Cloud Global Control Arbiter
↓
Robot / Linux Control Arbiter
↓
MCU Safety Interlock
三层检查。
Cloud 负责:
全局业务控制。
主要判断:
用户权限
设备归属
远程控制权
多客户端冲突
任务冲突
Remote Lease
Robot / Linux 负责:
本地执行控制。
主要判断:
LOCAL / REMOTE / AUTO / MAINTENANCE
当前 Task
当前 RobotState
Local Android 控制权
Navigation / Chassis 状态
Command 是否允许抢占
MCU / Safety 负责:
实时物理安全。
主要判断:
急停
碰撞
防跌落
驱动器故障
过流
Watchdog
失联保护
最终判断
所以:
Cloud ALLOW
≠
Robot 必须执行
而是:
Cloud
业务允许
↓
Robot
本地允许
↓
MCU
安全允许
↓
Execute
越靠近机器人和硬件,越掌握最新的真实状态。
因此:
上层负责调度,下层保留基于真实状态和安全条件的否决权。
如果是割草机器人:
App
↓
Cloud Global Arbiter
↓
Mower Local / Safety
↓
Hardware
由于远程业务入口主要经过 Cloud,云端承担的全局控制仲裁会更多。
如果是服务机器人:
手机 → Cloud ───┐
│
机身 Android ───┼→ Linux Control Arbiter
│
AUTO Task ──────┤
Maintenance ────┘
↓
MCU Safety
由于存在:
机身 Android
↓ TCP
Linux
这条本地直连控制链路,Linux 主控就必须成为:机器人本地控制状态的最终事实源。
到这里,我们可以把前面几个核心概念彻底区分开:
Command Center
解决:
指令生命周期怎么管理?
Control Arbiter
解决:
这条指令有没有资格执行?
Capability Owner
解决:
这个机器人能力到底属于谁?
Safety Interlock
解决:
物理上是否允许安全执行?
这四个角色组合起来,才逐渐形成一套真正完整的:
机器人可靠控制架构。
下一篇回到正式主线:
第 8 篇
《云柜机器人,本质上是在服务机器人底座上增加了哪些能力?》
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)