跳到主要内容

Robot PU 面向对象编程

完全没问题——让我们将你的智能跟随者群体机器人变成干净、模块化、专业的代码,使用:

  • 面向对象编程(OOP)
  • 事件处理器设计模式
  • micro:bit 事件系统(control.raiseEventcontrol.onEvent

本教程采用与 Robot PU JavaScript 教程系列相同的风格编写,但引入了真正的软件工程结构,使你的群体代码更易于维护、扩展和调试。

🤖 教程:使用 OOP + 事件处理器构建干净的智能跟随者机器人

Robot PU 群体跟随者需要:

  • 接收领导者朝向 + 速度
  • 计算转向 + 前进速度
  • 执行避障覆盖
  • 响应紧急情况
  • forever() 循环中平稳运行

原始代码可以工作,但它混合了:

  • 无线电解析
  • 指南针数学
  • 障碍物逻辑
  • 运动逻辑
  • 状态变量

……全部在一个地方。

让我们使用事件驱动架构来清理它。

🧱 1. 架构概述

我们将跟随者拆分为四个组件:

  1. RadioFollower(无线电跟随者)

监听无线电消息并触发事件。

  1. NavigationController(导航控制器)

根据领导者朝向计算转向 + 速度。

  1. ObstacleAvoidance(避障)

监控声呐并触发紧急/避障事件。

  1. SmartFollower(智能跟随者)

主机器人类,响应事件并驱动机器人。

这为我们提供了一个干净、模块化的系统:

Radio → Events → SmartFollower → Movement
Sonar → Events → SmartFollower → Movement

🧩 2. 定义事件 ID

我们使用 micro:bit 事件系统。

const EVT_FOLLOWER = 7001
const EVT_UPDATE = 1
const EVT_AVOID = 2
const EVT_EMERGENCY = 3

📡 3. RadioFollower 类

负责:

  • 接收 "heading,speed"
  • 解析
  • 触发更新事件
class RadioFollower {
heading: number = 0
speed: number = 0

constructor() {
radio.onReceivedString(msg => {
let parts = msg.split(",")
if (parts.length == 2) {
this.heading = parseInt(parts[0])
this.speed = parseInt(parts[1])
control.raiseEvent(EVT_FOLLOWER, EVT_UPDATE)
}
})
}
}

🧭 4. NavigationController 类

根据领导者朝向计算转向 + 速度。

class NavigationController {

computeTurn(targetHeading: number): number {
let myHeading = input.compassHeading()
let err = targetHeading - myHeading

if (err > 180) err -= 360
if (err < -180) err += 360

let turn = err / 90
if (turn > 1) turn = 1
if (turn < -1) turn = -1

return turn
}

computeSpeed(targetSpeed: number): number {
return targetSpeed / 50
}
}

🧱 5. ObstacleAvoidance 类

监控声呐并触发事件。

class ObstacleAvoidance {
EMERGENCY = 10
AVOID = 20

constructor() {
basic.forever(() => {
let d = robotPu.frontDistanceArray()[2]

if (d > 0 && d < this.EMERGENCY) {
control.raiseEvent(EVT_FOLLOWER, EVT_EMERGENCY)
} else if (d > 0 && d < this.AVOID) {
control.raiseEvent(EVT_FOLLOWER, EVT_AVOID)
}
})
}
}

🤖 6. SmartFollower 类(主机器人)

此类响应事件并驱动机器人。

class SmartFollower {
radio: RadioFollower
nav: NavigationController

constructor(r: RadioFollower, n: NavigationController) {
this.radio = r
this.nav = n

control.onEvent(EVT_FOLLOWER, EVT_UPDATE, () => this.followLeader())
control.onEvent(EVT_FOLLOWER, EVT_AVOID, () => this.avoidObstacle())
control.onEvent(EVT_FOLLOWER, EVT_EMERGENCY, () => this.emergencyStop())
}

followLeader() {
let fwd = this.nav.computeSpeed(this.radio.speed)
let turn = this.nav.computeTurn(this.radio.heading)
robotPu.walk(fwd, turn)
}

avoidObstacle() {
robotPu.walk(1.0, 0.9)
}

emergencyStop() {
robotPu.walk(0, 0)
basic.showIcon(IconNames.No)
}
}

🚀 7. 全部整合在一起

radio.setGroup(42)

let radioFollower = new RadioFollower()
let nav = new NavigationController()
let avoid = new ObstacleAvoidance()
let follower = new SmartFollower(radioFollower, nav)

就是这样——跟随者现在可以干净、模块化、事件驱动地运行了。

🎉 你刚刚构建了什么

你现在拥有一个专业级的群体跟随者:

面向对象

每个职责都隔离在自己的类中。

事件驱动

没有做所有事情的大型 forever() 循环。

清晰的关注点分离:

  • 无线电解析
  • 导航数学
  • 避障
  • 机器人运动

易于扩展

你可以添加:

  • 编队控制
  • 间距规则
  • 更平滑的避障
  • 滤波
  • 日志记录

而不触及核心逻辑。