外观
AI LLM
✅ 支持小智AI提供的大语言模型,能进行自然语言理解与处理。
MCP协议
✅ 支持MCP协议服务,LLM可通过MCP协议控制机器狗动作。
动作控制
✅ 支持通过自然语言控制,无需设置词条,均为LLM推理完成。
自定义唤醒
✅ 支持自定义名称唤醒机器狗,定制专属宠物。
软件开发
完整源码请在附件查看
BSP 模块
本项目采用 BSP(Board Support Package)板级适配架构,基于 xiaozhi-esp32 框架, 专门为EDA-Super Bear硬件平台定制,实现了AI语音控制的六关节机器熊功能。
- eda_super_bear.cc: 主板支持包,硬件抽象层实现
- eda_super_bear_controller.cc: 机器狗MCP控制器,实现动作队列和工具注册
- eda_super_bear_movements_clean.cc: 步态运动算法实现
- eda_super_bear_movements.h: 步态运动类定义和接口声明
- oscillator.cc / .h: 舵机振荡器实现,提供平滑运动控制
- config.h: 硬件引脚定义和系统参数配置
- config.json: ESP-IDF构建配置,定义目标平台和编译选项
eda_super_bear.cc
EDA SuperBear 硬件抽象层
硬件抽象层,负责硬件初始化和设备管理,包括音频编解码器、按键控制及机器人控制器。
class EdaSuperBear : public WifiBoard {
private:
Display* display_; // 显示屏实例
Button boot_button_; // Boot按键
Button touch_button_; // 触摸按键
void InitializeButtons(); // 初始化按键
void InitializeEdaSuperBearController(); // 初始化机器人控制器
public:
virtual AudioCodec* GetAudioCodec() override; // 获取音频编解码器
virtual Display* GetDisplay() override; // 获取显示屏
};eda_super_bear_controller.cc
EDA SuperBear MCP 控制器
机器人动作控制模块,实现各种运动模式和动作序列,包括行走、转向、跳跃、摇摆等基本动作和手部动作。
class EdaSuperBearController {
private:
EdaRobot edarobot_; // 动作执行器
QueueHandle_t action_queue_; // 动作队列
TaskHandle_t action_task_handle_; // 后台任务句柄
bool is_action_in_progress_; // 动作执行状态
bool has_hands_; // 是否有手部舵机
public:
void RegisterMcpTools(); // 注册MCP工具
void QueueAction(int type, int steps, int speed, int dir, int amount);
static void ActionTask(void* arg); // 后台动作执行任务
void LoadTrimsFromNVS(); // 加载舵机微调值
};eda_super_bear_movements.cc
SuperBear 动作库
双足机器人动作库,实现基于振荡器的平滑运动控制,支持行走、跳跃、摇摆、太空步等丰富动作。
class EdaRobot {
private:
Oscillator servo_[6]; // 6个舵机振荡器
int servo_pins_[6]; // 舵机引脚映射
int servo_trim_[6]; // 舵机微调值
bool has_hands_; // 是否有手部舵机
bool is_edarobot_resting_; // 休息状态
public:
void Init(int ll, int rl, int lf, int rf, int lh, int rh);
void Home(bool hands_down); // 复位到初始姿态
void SetTrims(int ll, int rl, int lf, int rf, int lh, int rh);
// 基础移动
void Walk(float steps, int period, int dir, int amount);
void Turn(float steps, int period, int dir, int amount);
void Jump(float steps, int period);
// 特殊动作
void Swing(float steps, int period, int height);
void Moonwalker(float steps, int period, int height, int dir);
void Bend(int steps, int period, int dir);
void ShakeLeg(int steps, int period, int dir);
void UpDown(float steps, int period, int height);
// 手部动作
void HandsUp(int period, int dir);
void HandsDown(int period, int dir);
void HandWave(int period, int dir);
};oscillator.h
Oscillator 振荡控制器
舵机振荡控制器,提供基于正弦波的平滑舵机运动控制,实现各种动作的精确执行。
class Oscillator {
private:
unsigned int amplitude_; // 振幅(度)
int offset_; // 偏移量(度)
unsigned int period_; // 周期(毫秒)
double phase0_; // 初始相位(弧度)
int trim_; // 微调值(校准)
double phase_; // 当前相位
int pos_; // 当前位置
bool stop_; // 停止标志
public:
void SetA(unsigned int amplitude); // 设置振幅
void SetO(int offset); // 设置偏移
void SetPh(double Ph); // 设置相位
void SetT(unsigned int period); // 设置周期
void SetTrim(int trim); // 设置微调
void Refresh(); // 刷新位置
int GetPosition(); // 获取位置
};config.json
config.json 配置文件
项目构建配置文件,定义目标平台、分区表和编译选项。
{
"target": "esp32s3",
"builds": [{
"name": "eda-super-bear",
"sdkconfig_append": [
"CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v1/16m.csv\""
]
}]
}实现原理
硬件抽象层架构
EDA SuperBear 板级支持包
基于 xiaozhi-esp32 框架的 BSP 架构,实现硬件抽象层,统一管理音频编解码器、按键控制等外设。
class EdaSuperBear : public WifiBoard {
private:
Display* display_ = nullptr;
Button boot_button_;
Button touch_button_;
void InitializeButtons() {
// Boot按键:切换聊天状态 / 重置WiFi
boot_button_.OnClick([this]() {
auto& app = Application::GetInstance();
if (app.GetDeviceState() == kDeviceStateStarting &&
!WifiStation::GetInstance().IsConnected()) {
ResetWifiConfiguration();
}
app.ToggleChatState();
});
// 触摸按键:按下录音,松开停止
touch_button_.OnPressDown([this]() {
Application::GetInstance().StartListening();
});
touch_button_.OnPressUp([this]() {
Application::GetInstance().StopListening();
});
}
public:
virtual AudioCodec* GetAudioCodec() override {
static NoAudioCodecSimplex audio_codec(
AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE,
AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK,
AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK,
AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN);
return &audio_codec;
}
};舵机振荡控制系统
Oscillator 振荡器实现
基于 LEDC PWM 的舵机控制器,通过正弦波振荡实现平滑的舵机运动,支持幅度、偏移、相位和周期控制。
bool Oscillator::NextSample() {
phase_ += inc_; // 相位递增
if (phase_ >= 2 * M_PI) {
phase_ -= 2 * M_PI;
return true; // 完成一个周期
}
// 正弦波位置计算
// position = amplitude * sin(phase + phase0) + offset + trim
int pos = round(amplitude_ * sin(phase_ + phase0_) + offset_ + trim_);
Write(pos); // 写入舵机
return false;
}
void Oscillator::Write(int position) {
// 限制角度范围 -90° 到 +90°
int angle = std::min(std::max(position, -90), 90);
// 转换为LEDC占空比
// 脉宽: 500-2500μs 对应 -90° 到 +90°
uint32_t duty = AngleToCompare(angle);
// 更新PWM输出
ledc_set_duty(ledc_speed_mode_, ledc_channel_, duty);
ledc_update_duty(ledc_speed_mode_, ledc_channel_);
}步态运动算法
Walk 行走算法实现
采用振荡器协调控制,通过精确的相位差实现双足机器人的平滑行走运动。
void EdaRobot::Walk(float steps, int period, int dir, int amount) {
// 定义6个舵机的振幅(运动幅度)
int amplitude[6] = {30, 30, 20, 20, amount, amount};
// 定义偏移量(基准位置)
int offset[6] = {0, 0, 4, -4, 0, 0};
// 定义相位差(控制腿部协调运动)
// 左右腿相位差90°实现交替抬腿
// 脚部与腿部同步运动
double phase_diff[6] = {
0, // 左腿
0, // 右腿
DEG2RAD(dir * -90), // 左脚
DEG2RAD(dir * -90), // 右脚
DEG2RAD(dir * -90), // 左手
DEG2RAD(dir * 90) // 右手
};
// 执行振荡运动
Execute(amplitude, offset, period, phase_diff, steps);
}MCP 协议集成
MCP 工具注册机制
通过 MCP 协议向 AI 大语言模型暴露机器人控制接口,支持参数验证和回调函数执行。
void EdaSuperBearController::RegisterMcpTools() {
auto& mcp_server = McpServer::GetInstance();
// 注册行走工具
mcp_server.AddTool(
"self.edarobot.walk_forward",
"行走。steps: 步数(1-100); speed: 速度(500-1500); "
"direction: 方向(-1=后退, 1=前进); arm_swing: 手臂摆动(0-170)",
PropertyList({
Property("steps", kPropertyTypeInteger, 3, 1, 100),
Property("speed", kPropertyTypeInteger, 1000, 500, 1500),
Property("arm_swing", kPropertyTypeInteger, 50, 0, 170),
Property("direction", kPropertyTypeInteger, 1, -1, 1)
}),
[this](const PropertyList& properties) -> ReturnValue {
int steps = properties["steps"].value();
int speed = properties["speed"].value();
int arm_swing = properties["arm_swing"].value();
int direction = properties["direction"].value();
// 将动作加入队列
QueueAction(ACTION_WALK, steps, speed, direction, arm_swing);
return true;
}
);
// 注册其他工具:jump, swing, turn, moonwalk...
}FreeRTOS 任务调度
异步动作执行系统
基于 FreeRTOS 队列的异步任务调度,确保动作执行不阻塞 AI 对话和其他系统功能。
static void ActionTask(void* arg) {
EdaSuperBearController* controller =
static_cast(arg);
EdaRobotActionParams params;
controller->edarobot_.AttachServos(); // 初始化舵机
while (true) {
// 从队列接收动作指令(阻塞等待)
if (xQueueReceive(controller->action_queue_, ¶ms,
pdMS_TO_TICKS(1000)) == pdTRUE) {
controller->is_action_in_progress_ = true;
// 根据动作类型执行相应动作
switch (params.action_type) {
case ACTION_WALK:
controller->edarobot_.Walk(params.steps, params.speed,
params.direction, params.amount);
break;
case ACTION_JUMP:
controller->edarobot_.Jump(params.steps, params.speed);
break;
case ACTION_SWING:
controller->edarobot_.Swing(params.steps, params.speed,
params.amount);
break;
// ... 其他动作
}
// 动作完成后自动复位(除了sit和showcase)
if (params.action_type != ACTION_HOME &&
params.action_type != ACTION_SIT) {
controller->edarobot_.Home(params.action_type < ACTION_HANDS_UP);
}
controller->is_action_in_progress_ = false;
vTaskDelay(pdMS_TO_TICKS(20));
}
}
}