上一篇,我们讨论了服务机器人为什么会存在多个控制入口。
例如:
机身 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_CHARGECloud 首先掌握的是:
全局业务信息。
例如:
当前用户是谁? 机器人属于谁? 这个用户有没有控制权限? 当前是否已经有人在远程控制? 当前是不是已经存在冲突任务? 是不是另一个 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_CONTROLCloud 判断:
当前已有远程控制者于是:
REJECT reason = REMOTE_CONTROL_OCCUPIED这种:
多用户 多 App 账号权限 控制租约问题显然非常适合在云端解决。
六、为什么可能还需要 Control Lease?
假设用户 A 获得了远程控制权。
然后:
手机断网Cloud 不能永久认为:
userA还在控制机器人。
所以可以设计:
Control Lease例如:
owner = userA expiresAt = 10s later客户端需要持续:
renew如果长时间没有续约:
Control Lease ExpiredCloud 就可以释放:
REMOTE CONTROL这和分布式系统中的:
Lease思想非常接近。
七、Cloud ALLOW 到底意味着什么?
这里一定要建立一个重要认知。
Cloud 返回:
ALLOW并不代表:
机器人必须执行。
它真正表示的是:
从云端当前掌握的全局业务状态来看,这条指令允许被下发。
也就是:
Cloud ALLOW = 允许发送给 Robot而不是:
Cloud ALLOW = Robot 必须执行这两个概念完全不同。
八、为什么 Robot 还必须再做一次仲裁?
因为 Cloud 不掌握机器人此刻最真实的本地状态。
例如 Cloud 当前记录:
mode = REMOTE state = IDLE于是允许:
RETURN_TO_CHARGE但是就在几百毫秒前,
现场用户通过机身 Android:
切换 LOCALLinux 当前真实状态已经变成:
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_CHARGELinux 通常没有必要重新判断:
这个用户是不是 VIP? 账号是否过期? 设备是不是属于这个用户?这些 Cloud 已经处理。
Linux 真正关心的是:
当前是不是 LOCAL? 机器人是不是正在 MAINTENANCE? 当前 AUTO Task 能不能被打断? 机器人是不是正在执行另一项高优先级任务? 当前 Navigation 是否允许启动新目标? 当前状态是不是 CHARGING? 是不是已经处于 RETURNING?这些属于:
本地机器人状态。
十一、服务机器人为什么尤其依赖本地仲裁?
因为它有一个非常重要的入口:
机身 Android ↓ TCP Linux这条链路:
根本不经过 Cloud。
例如:
手机 App ↓ Cloud ↓ RETURN_TO_CHARGECloud 判断:
ALLOW但与此同时,
现场用户:
机身 Android ↓ STOP_TASK甚至:
切换到 LOCALCloud 很可能还不知道这件事情。
但是 Linux 知道。
所以:
Linux Control Arbiter必须成为:
机器人本地控制状态的最终事实源。
十二、一个服务机器人指令可以这样走
例如手机远程点击:
RETURN_TO_CHARGE第一步:
手机 App ↓ CloudCloud 判断:
用户权限 ✓ 设备归属 ✓ 远程控制权 ✓ 任务冲突 ✓于是:
Cloud Arbiter → ALLOW然后:
Cloud Command Center ↓ MQTT LinuxLinux 收到以后:
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_FORWARDMCU 仍然:
拒绝执行甚至直接:
切断电机输出十六、为什么 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 / DeviceCommand Handler 负责:
解析 校验 去重 幂等Control Arbiter 负责:
当前是否允许执行Task / Navigation 负责:
真正完成机器人能力所以一个完整链路可以变成:
Command Center ↓ Communication ↓ Command Handler ↓ Control Arbiter ↓ Capability ↓ Hardware Adapter ↓ MCU Safety ↓ Hardware这时候前几篇内容就全部串起来了。
二十五、三级系统各自掌握什么“事实”?
这是理解多级仲裁最好用的方法。
Cloud
掌握:
全局业务事实。
例如:
用户是谁 设备属于谁 远程控制者是谁 任务历史 账号权限 远程 LeaseRobot / 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 ↓ CloudCloud Arbiter:
用户权限? ✓ 设备归属? ✓ 远程控制权? ✓ 业务任务冲突? ✓ ↓ ALLOWCommand Center:
创建 commandId = 1001然后:
MQTT ↓ RobotRobot 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_ACTIVECloud 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 LeaseRobot / 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 篇
《云柜机器人,本质上是在服务机器人底座上增加了哪些能力?》