中文文档机器人远控

机器人远控

final robot = RobotController(
  channel: MqttTeleopChannel(broker: 'mqtts://mqtt.example.com:8883'),
  gate: gate,           // epoch 管控,强烈建议接入
  rateLimiter: CommandRateLimiter(minInterval: const Duration(milliseconds: 100)),
);
await robot.connect(deviceId: 'robot-42');

驾驶

// 由摇杆偏移换算
final v = velocityFromJoystick(dx: 0.4, dy: -0.8, maxLinear: 1.0, maxAngular: 1.5);
await robot.move(v);
 
// PTZ 走独立通道,绝不进 WebRTC
await robot.setPtz(pan: 30, tilt: -10);
 
// 显式停车:撤防看门狗,且一定送达
await robot.stop();

指令每 commandInterval(默认 100ms)重发一次,丢一个包也不会让机器人盲开。

看门狗

事件行为
超过 watchdogTimeout(500ms)没有新指令立即停车 + 上报 RobotWatchdogTriggered
通道拒绝发送立即停车——被拒意味着失去控制,而不是”稍后再试”
通道断开与指令超时同等处理
robot.events.whereType<RobotWatchdogTriggered>().listen((e) {
  showBanner('看门狗触发:${e.sinceLastCommand.inMilliseconds} ms');
});

:::warning 看门狗是安全特性,不是便利开关。不要把 watchdogTimeout 调到机器人能承受的范围 之外——500ms 这个预算存在的理由,是机器人收完最后一个包还会继续动。 :::

暂停 / 恢复(防止事故的关键)

// 应用进后台或链路中断
await robot.pause(PauseReason.background);
// → 立即发 stop
// → 撤防看门狗
// → epoch++,此前所有指令失效
 
// 回来必须确认
final ticket = robot.requestResume();
final ok = await robot.confirmResume(ticket);

保证如下:

  • 挂起期间采集到的摇杆位置被丢弃而非补发,机器人不会因过期输入重新动起来;
  • 保活循环每拍重新校验 epoch,暂停前的速度无法溜过去;
  • 外来或过期票据一律拒绝并上报原因。
robot.events.whereType<RobotStaleCommandDropped>().listen((e) {
  debugPrint('丢弃 epoch ${e.epoch},当前 ${e.currentEpoch}');
});

遥测

robot.channel.telemetry.listen((t) {
  debugPrint('电量 ${t.battery} · 速度 ${t.speed}');
});

选择控制通道

final selection = ControlLinkRouter(rttBudgetMs: 200).select(paths);
通道适用
ControlLinkKind.dataChannel首选——随 WebRTC 连接走,约 12ms
ControlLinkKind.mqtt跨公网 / 跨区域回退,约 180ms

路由器还会报告所选路径是否在 rttBudgetMs 预算内,让 UI 在操作员开动之前就给出 提示。