犀牛派 A1 实战:把开源 MindPaw 改造成端侧 AI 情感机器狗

zhaomingming2671 2026-09-20 15:47:27

最近看到一个比较有意思的开源项目:

MindPaw。

它是一只桌面级四足机器狗,原始项目使用 ESP8266 作为主控,同时集成了:

  • 四足舵机运动;
  • OLED 表情;
  • 离线语音命令;
  • OV2640 摄像头;
  • 手势识别;
  • 豆包大模型对话;
  • PAD 情感状态机;
  • 网页遥控;
  • 简单的多模态融合。

原项目甚至在后续版本中增加了 Edge Gateway 和流式视觉感知层,将摄像头画面传到边缘节点进行感知计算,项目本身已经很好玩了。

但看完代码以后,我产生了另外一个想法:

如果把 ESP8266 上承担不了的 AI 能力全部搬到犀牛派 A1,会发生什么?
于是有了这次改造,最终目标不是简单做一只可以遥控的机器狗,而是一只能够:

看见你
  ↓
理解手势
  ↓
听懂指令
  ↓
理解上下文
  ↓
产生自己的“情绪”
  ↓
选择动作和表情
  ↓
与你进行自然交互

的端侧 AI 机器人。


1. 先看看原版 MindPaw

MindPaw 原项目基于 ESP8266,项目把大量功能都塞到了这颗资源非常有限的 MCU 中,包括动作控制、OLED、语音、手势、多模态融合以及云端大模型调用。原代码中的 multimodal_fusion.cpp 会把文本、语音命令和手势统一转换成上下文,再送入情感系统;emotion_engine.cpp 则维护 Pleasure、Arousal、Dominance 三维 PAD 情绪状态。
整体结构大概是:

                 OV2640
                    │
                    ▼
               ESP8266
           ┌────────┼────────┐
           │        │        │
         手势     语音     Web
           │        │        │
           └──── 多模态融合 ──┘
                    │
                    ▼
               PAD 情感
                    │
                    ▼
               豆包 API
                    │
          ┌─────────┼─────────┐
          ▼         ▼         ▼
        Action   Expression  Melody
          │
          ▼
       SG90 × 4

甚至大模型返回的数据也已经不是普通聊天文字,原项目会解析类似:

{
  "reply_text": "主人你好呀!",
  "action": 12,
  "expression": 0,
  "melody": 5,
  "emotion": 1
}

然后分别驱动机器人动作、OLED 表情、旋律和 PAD 情绪状态,这个设计思路其实很好。

真正的问题只有一个:
ESP8266 太小了,视觉模型、大模型、复杂 ASR 以及环境感知都只能往外部服务器或者云端搬。


2. 为什么换成犀牛派 A1?

犀牛派 A1 基于 Qualcomm Dragonwing QCS6490,目前官方规格包括:

Qualcomm QCS6490
约 12 TOPS INT8 AI 算力
8GB LPDDR4
128GB UFS 3.1
Adreno 643 GPU
Wi-Fi 6
USB 3.0 × 4
MIPI D-PHY Camera
UART / SPI / GPIO
双网口

并支持 AidLux 融合系统以及 Ubuntu,于是原项目中很多需要外部机器完成的事情,可以直接搬回机器狗本地:

原版 MindPaw

ESP8266
   │
   ├── 简单手势
   ├── 简单语音
   └── WiFi
         ↓
       云端
         ↓
       LLM

变成:

MindPaw-A1

                犀牛派 A1
       ┌───────────┼───────────┐
       │           │           │
     Camera       ASR        Web/API
       │           │           │
       ▼           ▼           │
      NPU       语音文本        │
       │           │           │
       └────── 多模态融合 ──────┘
                   │
              PAD 情感状态
                   │
                   ▼
              Local LLM
                   │
                   ▼
                Agent
                   │
          ┌────────┼────────┐
          │        │        │
       action  expression  reply
          │
          ▼
         MCU
          │
       SG90 × 4

这样 A1 就从原项目里的“外部 Gateway”,真正变成机器人的:

Edge AI Brain。


3. 不建议直接用 A1 控四个舵机

这里是这次改造里一个比较重要的决定,我没有选择:

A1 GPIO
 ↓
SG90 ×4

而是:

A1
 ↓
UART
 ↓
ESP8266 / ESP32 / STM32
 ↓
Servo

原因很简单。

Linux + AI SoC 擅长:

视觉
语音
大模型
Agent
网络
Web
数据库
复杂逻辑

MCU 擅长:

PWM
舵机
毫秒级时序
硬实时控制
掉线后的安全动作

机器人里面没有必要让一个 Linux AI SoC 去抢 MCU 的工作,因此原 MindPaw 的机械结构、四个 SG90 以及大量运动代码都可以继续保留,我们只把 ESP8266 从:

“机器人主脑”

降级成:

“机器人运动控制器”。


4. 改造后的硬件组成

最终硬件可以采用:

硬件作用
犀牛派 A1AI 主脑
ESP8266 / ESP32舵机实时控制
SG90 × 4四足运动
IMX577 / USB Camera机器人视觉
USB 麦克风语音输入
Speaker语音/声音反馈
SSD1306 OLED表情显示
原 MindPaw 3D 外壳机械结构

需要特别注意:

A1 不一定非要塞进原版很小的机器狗身体里。

第一版验证完全可以:

机器狗本体
   │
 UART / USB / WiFi
   │
   ▼
桌面上的 Rhino Pi-A1

先跑通系统,后面再针对 A1 重新设计机器人身体结构,这样开发效率高很多。


5. 摄像头也不再使用 OV2640

原 MindPaw 使用 OV2640,原项目为了适配 ESP8266 的资源限制,视觉数据非常受限;其 2.0 文档也明确提到,早期手势视觉只使用非常低分辨率的数据,后续空间感知还需要把 JPEG 推送给外部 Gateway,到了 A1 完全没必要继续这么做。

A1 原生提供 D-PHY Camera 接口,目前官方文档支持 IMX577 12MP 摄像头,同时也有多个 USB 3.0 Host 接口。

所以直接:

IMX577Rhino Pi-A1OpenCV / AidCV
  ↓
AidLiteQNNNPU

6. 手势识别也搬到 QCS6490

原项目中:

OV2640
 ↓
低分辨率图像
 ↓
轻量 MLP
 ↓
gestureClass

到了 A1,可以改成:

Camera
 ↓
Hand Detection / Keypoint
 ↓
QNN NPU
 ↓
手部关键点
 ↓
Gesture Classifier
 ↓
WAVE / FIST / POINT / PALM

APLUX Model Farm 当前已经收录 MediaPipe-Hand 等视觉模型,同时 Model Farm 整个平台支持 QCS6490;实际部署时可以先运行:

mms login

mms list MediaPipe-Hand

确认当前提供的 QCS6490 模型变体和对应 QNN Backend,再下载相匹配的模型。Model Farm 也明确支持通过 mms listmms get 按 SoC、精度和 Backend 获取优化后的模型,如果只想先验证整个系统,也完全可以暂时保留 MindPaw 原来的四种手势:

1 = 挥手
2 = 伸掌
3 = 握拳
4 = 指点

原项目多模态模块本身已经定义好了这些手势语义。


7. 最关键的变化:把豆包云端大脑换成本地模型

原 MindPaw 使用:

ESP8266
 ↓
HTTPS
 ↓
豆包 API

如果网络断了,就只能进入 fallback。

原代码中的离线回复甚至直接包含:

“我的大脑掉线了,请稍后再试~”

这种设计。

A1 版最值得做的改造,就是:

让机器狗断网以后仍然有“大脑”。

APLUX Model Farm 当前已经提供专门针对 QCS6490 的:

Qwen2.5-0.5B-Instruct (QCS6490)

Precision:
W8A16

并推荐通过 AidGen / AidGenSE 推理。官方模型页面明确把它定位为适用于边缘设备和低资源环境的轻量指令模型。

因此 MindPaw-A1 可以使用:

Qwen2.5-0.5B
     ↓
QCS6490
     ↓
Local Agent

完全不经过公网。


8. 为什么 0.5B 就够了?

因为这里不是让机器狗帮我们写论文。

机器人 Agent 最主要的任务是:

理解:
“过来”

“跟我打个招呼”

“你今天开心吗?”

“坐下”

“看到我挥手了吗?”

        ↓

转换成:

{
 action,
 expression,
 reply,
 emotion
}

这种任务最重要的反而是:

指令遵循 + JSON 输出稳定。

而不是模型参数越大越好。

因此可以给模型一个非常严格的 System Prompt。

例如:

你是一只名叫 MindPaw 的桌面机器狗。

你的任务不是长篇聊天,
而是根据用户输入、视觉状态和自身情绪,
生成机器狗下一步行为。

只允许输出 JSON:

{
  "reply_text": "",
  "action": 0,
  "expression": 0,
  "emotion": 0
}

action:

0 = 不动作
1 = 前进
2 = 后退
3 = 停止
4 = 左转
5 = 右转
6 = 坐下
7 = 趴下
8 = 抬左手
9 = 抬右手
10 = 摇头
11 = 跳舞
12 = 点头

expression:

0 = 开心
1 = 生气
2 = 普通
3 = 好奇
4 = 喜爱
5 = 难过

任何情况下不得输出未定义动作。

这样 LLM 的角色不再是:

ChatBot

而是:

Semantic Planner

9. 保留 MindPaw 最有意思的 PAD 情感系统

我认为原项目里面最值得保留的代码之一,就是:

emotion_engine.cpp

它不是简单维护:

happy = true

而是使用:

Pleasure
Arousal
Dominance

三个连续变量。

比如原代码中快乐情绪的 PAD 原型约为:

P = +0.81
A = +0.65
D = +0.57

情绪也会随着时间逐渐向 baseline 衰减。

这一部分搬到 A1 后完全可以改写成 Python:

from dataclasses import dataclass


@dataclass
class PADState:
    pleasure: float = 0.0
    arousal: float = 0.3
    dominance: float = 0.5


class EmotionEngine:

    def __init__(self):

        self.baseline = PADState()

        self.state = PADState()


    @staticmethod
    def clamp(x, low, high):
        return max(low, min(high, x))


    def ema(self, current, target, rate):

        return (
            current
            + rate * (target - current)
        )


    def update_from_gesture(
        self,
        gesture,
        confidence
    ):

        target_p = 0.0
        target_a = 0.3

        if gesture == "wave":

            target_p = 0.2
            target_a = 0.5

        elif gesture == "fist":

            target_p = -0.1
            target_a = 0.6


        self.state.pleasure = self.ema(
            self.state.pleasure,
            target_p,
            0.15 * confidence
        )

        self.state.arousal = self.ema(
            self.state.arousal,
            target_a,
            0.1
        )


    def decay(self):

        self.state.pleasure = (
            0.97 * self.state.pleasure
            + 0.03 * self.baseline.pleasure
        )

        self.state.arousal = (
            0.98 * self.state.arousal
            + 0.02 * self.baseline.arousal
        )

        self.state.dominance = (
            0.99 * self.state.dominance
            + 0.01 * self.baseline.dominance
        )

原来的思想基本不用改变。

区别只是:

以前:

Emotion Engine
运行在 ESP8266

现在:

Emotion Engine
运行在 Linux Python

这样后面就更容易接入:

视觉
语音
LLM
用户画像
环境状态
长期记忆

10. 多模态输入统一成 Event

我也不建议把原来的代码简单照搬。

在 Linux 上可以进一步把所有输入统一成事件:

{
  "source": "gesture",
  "type": "wave",
  "confidence": 0.93,
  "timestamp": 1789900000
}

语音:

{
  "source": "voice",
  "text": "过来",
  "timestamp": 1789900001
}

视觉:

{
  "source": "vision",
  "person_detected": true,
  "distance": 1.2,
  "gesture": "wave"
}

Web:

{
  "source": "web",
  "text": "跳个舞"
}

全部进入:

Event Bus
Multimodal Fusion
   ↓
Emotion Engine
   ↓
Agent

这比在每一个硬件回调里面写业务代码更加容易维护。


11. A1 端新的项目结构

我会把原仓库重构成这样:

MindPaw-A1/
│
├── brain/
│   │
│   ├── main.py
│   │
│   ├── agent.py
│   │
│   ├── emotion.py
│   │
│   ├── fusion.py
│   │
│   └── config.py
│
├── vision/
│   │
│   ├── camera.py
│   ├── hand_detector.py
│   ├── gesture.py
│   └── person_detector.py
│
├── speech/
│   │
│   ├── asr.py
│   └── tts.py
│
├── actuator/
│   │
│   ├── serial_controller.py
│   └── protocol.py
│
├── web/
│   ├── app.py
│   └── static/
│
├── models/
│
├── mcu/
│   └── MindPaw_MotionController/
│
├── configs/
│   └── robot.yaml
│
└── README.md

这时候 A1 上的程序已经非常像真正的机器人软件架构。


12. A1 和运动 MCU 之间定义一个简单协议

例如使用 UART。

A1 本身提供 3.3V UART 等扩展接口。

A1 → MCU:

{
  "type": "action",
  "action": "wave_left",
  "speed": 0.7
}

MCU 返回:

{
  "type": "action_result",
  "action": "wave_left",
  "status": "done"
}

Python 可以写得非常简单:

import json
import serial


class MotionController:

    def __init__(
        self,
        port="/dev/ttyUSB0",
        baudrate=115200
    ):

        self.serial = serial.Serial(
            port,
            baudrate,
            timeout=1
        )


    def send_action(
        self,
        action,
        speed=0.7
    ):

        message = {
            "type": "action",
            "action": action,
            "speed": speed
        }

        payload = (
            json.dumps(message)
            + "\n"
        )

        self.serial.write(
            payload.encode()
        )

这样 AI 层永远不需要知道:

左前腿舵机是多少度
右后腿 PWM 是多少

它只需要说:

robot.send_action("sit")

13. MCU 只负责确定性动作

MCU 固件则继续复用 MindPaw 原来的动作代码。

例如:

void executeAction(String action)
{
    if (action == "forward")
    {
        moveForward();
    }
    else if (action == "backward")
    {
        moveBackward();
    }
    else if (action == "sit")
    {
        sitDown();
    }
    else if (action == "wave_left")
    {
        waveLeft();
    }
    else if (action == "dance")
    {
        dance();
    }
    else if (action == "stop")
    {
        stopAllServos();
    }
}

最终就形成:

QCS6490
负责“我要做什么”


MCU
负责“这个动作具体怎么做”

这个边界非常重要。


14. 做一个真正的 A1 Robot Agent

然后我们把所有模块串起来。

class MindPawAgent:

    def __init__(
        self,
        llm,
        emotion,
        motion
    ):

        self.llm = llm

        self.emotion = emotion

        self.motion = motion


    def process(
        self,
        text,
        vision=None
    ):

        state = self.emotion.state


        context = {

            "user": text,

            "vision": vision,

            "emotion": {

                "pleasure":
                    state.pleasure,

                "arousal":
                    state.arousal,

                "dominance":
                    state.dominance
            }
        }


        result = self.llm.chat(
            context
        )


        action = result.get(
            "action",
            "none"
        )


        if action != "none":

            self.motion.send_action(
                action
            )


        return result

例如用户说:

“看到我了吗?”

视觉模块当前检测到:

{
  "person": true,
  "gesture": "wave",
  "confidence": 0.94
}

情感系统当前状态:

{
  "pleasure": 0.56,
  "arousal": 0.61,
  "dominance": 0.51
}

LLM 最终可以生成:

{
  "reply_text": "当然看到啦,你还在跟我挥手呢!",
  "action": "wave_left",
  "expression": "happy",
  "emotion": "happy"
}

机器人:

OLED → 开心

左腿/前肢 → 挥手动作

Speaker → 播放回应

PAD → Pleasure 上升

整个交互就闭环了。


15. 现在的机器狗可以主动响应了

原来更多是:

用户
 ↓
命令
 ↓
机器人

A1 版可以增加主动事件。

比如视觉持续发现:

person = true
gesture = wave

系统可以生成事件:

EVENT_PERSON_GREETING

然后:

Camera
   ↓
手势识别
   ↓
发现 Wave
   ↓
Emotion Engine
   ↓
Pleasure ↑
Arousal ↑
   ↓
Agent
   ↓
“你好呀!”
   ↓
Wave Action

于是用户甚至不用说话。

机器狗看到你挥手以后,也会主动回应。


16. 再加一个“无聊”状态

PAD 系统还有一个很好玩的应用。

如果:

5分钟
没有用户
没有语音
没有手势

可以逐渐降低:

Arousal
Pleasure

例如:

if idle_seconds > 300:

    emotion.state.arousal -= 0.05
    emotion.state.pleasure -= 0.02

达到阈值以后:

Emotion = BORED

机器人自动:

趴下
 ↓
OLED 困倦表情
 ↓
偶尔抬头

用户再次出现:

Person Detected
 ↓
Arousal ↑
 ↓
抬头
 ↓
“你终于回来啦!”

这种交互比单纯遥控机器狗明显更有意思。


17. 原 MindPaw 2.0 的 Edge Gateway 也可以收回来了

原版 2.0 的设计是:

OV2640
 ↓
ESP8266
 ↓
WiFi POST
 ↓
Edge Gateway
 ↓
视觉模型
 ↓
Hazard
 ↓
ESP8266

文档里给出的默认架构甚至需要通过 HTTP 上传 JPEG,再由 Gateway 回传 hazard。

A1 版可以直接改成:

CameraA1NPUDepth / DetectionHazard

无需:

JPEG Encode
WiFi POST
HTTP
Gateway
HTTP Response

也就是:

原来:

Robot
 ↓
Network
 ↓
Edge AI


现在:

Robot
 ↓
On-device AI

这实际上才是这次改造最大的意义。


18. 可以增加人物检测和安全逻辑

例如在 A1 上运行 YOLO。

Model Farm 当前明确存在面向 QCS6490 的 YOLOv5s INT8 和 W8A16 版本,可使用 QNN 后端运行。

于是:

Camera
 ↓
YOLO
 ↓
person
 ↓
距离 / 区域
 ↓
Safety Layer

这里要强调一点:

LLM 不能直接拥有最终电机控制权。

正确结构应该是:

LLM Agent
     │
     ▼
Requested Action
     │
     ▼
Safety Layer
     │
     ├── 是否有人挡路?
     ├── 是否正在执行动作?
     ├── action 是否在白名单?
     ├── 是否超时?
     └── 是否存在 STOP 事件?
     │
     ▼
Motion MCU

例如模型输出:

{
  "action": "forward"
}

但视觉检测:

前方有人

安全层直接修改:

forward
   ↓
REJECT
   ↓
stop

而不是相信 LLM。


19. 我会给动作指令增加白名单

SAFE_ACTIONS = {

    "none",
    "stop",

    "forward",
    "backward",

    "turn_left",
    "turn_right",

    "sit",
    "lie_down",

    "wave_left",
    "wave_right",

    "nod",
    "shake_head",

    "dance"
}


def validate_action(action):

    if action not in SAFE_ACTIONS:

        return "stop"

    return action

无论模型输出什么:

destroy_world
jump_from_table
servo_180000

最终都无法进入 MCU。


20. 最终的数据链路

这样整个 MindPaw-A1 就完整了:

                     Camera
                       │
             ┌─────────┴─────────┐
             │                   │
        Gesture Model          YOLO
             │                   │
             └─────────┬─────────┘
                       │
USB Mic ── ASR ────────┤
                       │
Web / App ──────────────┤
                       │
                       ▼
              Multimodal Fusion
                       │
                       ▼
                PAD Emotion
                       │
                       ▼
              Qwen2.5-0.5B
                QCS6490
                       │
                       ▼
                  AI Agent
                       │
          ┌────────────┼────────────┐
          │            │            │
        Reply        Action      Expression
          │            │            │
          │            ▼            │
          │       Safety Layer      │
          │            │            │
          │            ▼            │
          │       UART / USB        │
          │            │            │
          │            ▼            │
          │           MCU           │
          │            │            │
          │         SG90 × 4        │
          │                         │
          └──── Speaker       OLED ─┘

21. 和原 MindPaw 相比到底升级了什么?

能力原 MindPawMindPaw-A1
主控ESP8266QCS6490 + MCU
AI 算力基本无约 12 TOPS
CameraOV2640IMX577 / USB Camera
手势轻量 MLPNPU 视觉模型
LLM云端豆包本地 Qwen + 云端可选
情感系统PADPAD 保留并增强
多模态简单融合Event-driven Fusion
AI Gateway外置服务器A1 本地
视觉感知GatewayNPU 本地
WebESP8266 WebLinux Web Service
数据存储很有限SQLite / 文件 / UFS
Agent云端响应本地 Robot Agent
断网AI 基本失效核心能力仍可工作

这里不是说:

“A1 比 ESP8266 性能高,所以项目升级了。”

真正发生的变化其实是:

MCU Robot
       ↓
Edge AI Robot

22. 建议的实际开发顺序

如果真的准备动手,我不建议一天把所有功能都做完。

第一阶段只做:

A1
 ↓
UART
 ↓
ESP8266
 ↓
四路 Servo

先能够:

forward
backward
left
right
sit
stop

第二阶段:

Camera
 ↓
OpenCV
 ↓
A1

先能稳定获取画面。


第三阶段:

Camera
 ↓
手势识别
 ↓
wave
 ↓
机器人挥手

完成第一个 AI 闭环。


第四阶段:

Qwen2.5-0.5B
 ↓
JSON
 ↓
action
 ↓
Robot

实现自然语言控制。


第五阶段:

Vision
+
Voice
+
Text
+
PAD
+
LLM
        ↓
Multimodal Agent

最后再加入完整的情感交互。

这样哪个阶段出了问题都非常容易定位。


23. 最终 Demo 可以怎么玩?

最终做展示时,可以设计下面这样的流程。

用户走到机器狗前面。

摄像头检测到:

person detected

机器狗抬头。

用户挥手:

gesture = wave

机器人:

OLED:
^_^

动作:
抬左手

PAD:
Pleasure ↑
Arousal ↑

然后用户说:

“今天心情怎么样?”

ASR:

今天心情怎么样

送入 Agent:

User:
今天心情怎么样?

Current Emotion:
P = 0.72
A = 0.61
D = 0.52

Vision:
person = true
gesture = wave

本地 Qwen 输出:

{
  "reply_text": "看到你来找我,我当然很开心呀!",
  "action": "nod",
  "expression": "happy",
  "emotion": "happy"
}

然后:

机器人点头
+
OLED 开心
+
语音回复

这时候它已经不是:

“一个可以远程控制的四足玩具。”

而开始接近:

一台具备视觉、语言、情绪状态和行为反馈的端侧具身 AI Demo。


24. 总结

MindPaw 原项目真正有价值的不是四个 SG90。

而是它已经把:

动作
视觉
语音
表情
情绪
LLM

尝试组合成了一个完整交互机器人。

原项目最新架构甚至已经明确提出设备本地、Edge Gateway 和云端之间进行任务分层。

而犀牛派 A1 的意义,就是把原本:

ESP8266
+
Edge Gateway
+
Cloud AI

重新收敛为:

             Rhino Pi-A1
                 │
       Qualcomm QCS6490
                 │
       ┌─────────┼─────────┐
       │         │         │
     Vision     LLM      Agent
       │         │         │
       └─────────┼─────────┘
                 │
              Emotion
                 │
                 ▼
                MCU
                 │
                 ▼
              Robot

底层 MCU 依旧负责稳定、确定性的实时控制,QCS6490 则负责:
感知、理解、决策和交互。
这也是我认为 MindPaw 最适合迁移到犀牛派 A1 的方式:

不是用一块更强的开发板替换 ESP8266,而是重新划分机器人的“脑”和“身体”。
从一个低成本 MCU 机器狗 Demo,升级成一个真正可以继续研究端侧 Agent、多模态交互和具身智能的机器人平台。

...全文
47 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

7,697

社区成员

发帖
与我相关
我的任务
社区描述
本论坛以AI、IoT、PC 、XR、Auto等核心板块组成,为开发者提供便捷及高效的学习和交流平台。 高通开发者专区主页:https://qualcomm.csdn.net/
物联网人工智能开源 企业社区 北京·东城区
社区管理员
  • csdnsqst0050
  • chipseeker
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧