本页目录

二次开发

TARS 固件代码现已在 LuwuDynamics/rig_omni 公开。这里从零完成一次能看见结果的修改:准备工具 → 下载源码 → 选择 TARS 和国内版 → 编译原版 → 烧录并查看日志 → 修改一句启动提示 → 选做 MCP 与资源开发 → 恢复原版。

先完成整机安装、标定、配网和普通对话。只想正常使用或给电子套件烧录正式固件,可直接使用 国内烧录平台;不必先学习编程。套件装配流程见总装与配置。

1. 先认识几个词

名称在这篇教程里的意思
源码可以编辑的程序文本。
固件编译后写入机器人、在机器人上运行的程序。
ESP-IDF乐鑫提供的 ESP32 开发工具和库。
终端输入命令、查看执行结果的窗口。
编译 / build在电脑上把源码转换成固件;这一步不会写入机器人。
烧录 / flash把编译结果写入机器人。
串口电脑与主板的通信端口,例如 COM5。
monitor / 日志在电脑上查看固件输出的信息。

准备一根 USB 数据线、有网络的电脑和已能正常使用的 TARS。先记录主板版本、当前固件版本和重新获取对应正式固件的方法。普通编译不改变机器人;烧录会更换程序,全片擦除还可能清掉设备设置,不要将擦除作为默认排错步骤。

2. 安装工具,打开 ESP-IDF 终端

首次操作建议使用 ESP-IDF 5.5.3。公开仓库的依赖要求至少 5.5.2,README 记录的 TARS 构建环境为 5.5.3。先保持一个已知环境,不要同时升级工具链和改固件。

  1. 安装 Git,用于下载和管理源码。
  2. 按乐鑫 ESP32-S3 安装指南安装 ESP-IDF,选择 5.5.3 和 ESP32-S3 工具链,等待依赖全部下载完成。
  3. 打开安装工具提供的 ESP-IDF PowerShell / 命令行环境。普通终端不一定已加载编译器路径。
  4. 安装文本编辑器,例如 VS Code。编辑器用于改文件,ESP-IDF 终端用于执行命令。
  5. 在终端逐行运行:
git --version
python --version
idf.py --version

三个命令都应输出版本,最后一个应显示 ESP-IDF 5.5.3。构建时使用 ESP-IDF 安装器管理的 Python 环境;仓库工具脚本要求 Python 3.10 或更新版本。若提示找不到命令,先重新打开对应的 ESP-IDF 环境。

macOS / Linux 用户使用同一官方指南的对应系统说明。每次打开新终端都需激活 ESP-IDF;传统安装通常在 ESP-IDF 安装目录执行 . ./export.sh,不是在机器人源码目录执行它。后面的 Git 和 IDF 命令相同,目录和串口按自己的系统替换。

3. 下载公开源码,确认项目目录

Windows 用户可先用文件资源管理器创建 C:\rig-work,然后在 ESP-IDF 终端执行:

cd C:\rig-work
git clone --branch main https://github.com/LuwuDynamics/rig_omni.git
cd rig_omni
git switch -c my-first-tars-change
git status --short

macOS / Linux 用户选择自己的工作目录,再执行相同的 clone 命令。用编辑器打开 rig_omni 文件夹,应能看到根目录的 CMakeLists.txt、main 和 sdkconfig.defaults。后续 IDF 命令都在这个根目录执行。

git switch -c 只创建本地实验分支,不会把修改发布到 GitHub。若目录或分支已经存在,先检查是不是自己正在使用的项目;保留修改,也可以下载到另一个空目录。旧源码中没有 TARS 时,不要选择 Puppy 或 Arm 替代。

4. 选择芯片、TARS 板型和国内版

idf.py set-target esp32s3
idf.py menuconfig

在 RIG-Omni 菜单里逐项检查:

选项本篇选择
Board TypeRIG-Tars,对应 CONFIG_BOARD_TYPE_TARS。
Firmware RegionDomestic (China)。后续使用小陆同学和国内配置平台。
Select display styleEmote animation style。
Flash AssetsFlash Emote Assets。

按界面提示保存到 sdkconfig 并退出。项目默认板型是 Puppy,选择 ESP32-S3 并不等于选好了 TARS。TARS 的 320 × 240 横屏布局由板型配置决定,先保留引脚、屏幕方向、分区和 PSRAM 默认配置。

第一次烧录或切换区域时,应用程序和资源必须配套烧录。国内页使用国内固件、配网二维码和账号服务,不要混用国际版资源或服务地址。

5. 先编译未经修改的程序

idf.py build

首次运行会下载依赖并生成构建文件,通常比后续编译慢。等待命令成功结束,看到构建完成提示后再继续。若原版无法编译,先解决报错,不要同时加入自己的代码。

保存一份本地 sdkconfig,并记录工具链版本、源码版本、板型和区域。build/ 是生成目录,不要直接编辑里面的文件;单独一个应用 .bin 不一定是完整烧录包。

6. 找到串口并烧录原版

  1. 拔下 USB,在 Windows 设备管理器中观察“端口(COM 和 LPT)”。
  2. 用数据线连接 TARS 主板的正确接口,找到新出现的端口。
  3. 拔插一次确认端口确实属于机器人。下面的 COM5 只是例子。
  4. 关闭浏览器烧录页、其他串口助手和编辑器串口监视器,避免端口被占用。
  5. 按套件要求供电,扶稳机器人,给关节留出活动空间,再执行:
idf.py -p COM5 flash monitor

macOS 的端口通常形如 /dev/cu.…,Linux 通常为 /dev/ttyACM… 或 /dev/ttyUSB…,都要通过插拔确认,不能照抄。

**找不到串口?**按烧录平台提示尝试安装 CH340/CP210x 驱动,重新插拔后检查;同时确认使用数据线、端口权限和端口占用情况。需要手动进入下载模式时,按主板对应说明操作,不能把日常恢复出厂的长按动作当作通用下载步骤。

烧录期间不要断电或拔线。完成后会进入串口日志监视器,持续打印是正常的。按 Ctrl + ] 退出。只想重新看日志、不重新烧录时执行:

idf.py -p COM5 monitor

若没有有效零位数据,TARS 会进入标定:等待舵机归中并卸力,按 TARS 标定要求摆好已装配整机,再轻触外置触摸模块确认。原有有效标定可能直接载入,不一定每次烧录都要求重新标定。若显示红色错误提示,按本页排错表处理。

标定完成后,根据屏幕二维码进入 小陆同学,连接 2.4 GHz Wi-Fi,完成设备配置;智能体可在小程序或国内网页配置平台设置。先确认屏幕、配网和一次对话正常。

7. 第一次修改:在启动日志中加一句话

打开 main/boards/tars/tars_board.cc,搜索 void InitializeTools(),在这个函数的左花括号之后加入一行,保留其余原代码:

ESP_LOGI(TAG, "My first TARS firmware is running");

ESP_LOGI 表示输出普通信息日志,TAG 是当前模块标签,引号中是你写的文字。用英文直引号,行末保留分号。不要新建第二个同名函数,也不要覆盖整个文件。

保存文件,查看改动:

git diff -- main/boards/tars/tars_board.cc
idf.py build

确认只增加了预期一行,且构建成功,再用自己的端口执行:

idf.py -p COM5 flash monitor

**成功标志:**电脑日志出现 My first TARS firmware is running,并且机器人仍能正常启动和对话。这句话显示在电脑终端,不会自动变成语音,也不会显示在机器人屏幕上。

没有出现时,检查是否保存文件、板型是否选对、烧录是否成功、串口是否对应这台机器人、日志是否允许输出 Info 级别。编译成功不等于已经烧录。

8. Vibe Coding:让 AI 帮你完成同一个小修改

可以用能读取本地工程的 AI 编程助手打开 rig_omni,先让它解释现有代码,再改一件小事。若使用普通聊天工具,需要把相关函数和上下文提供给它;只贴仓库链接不保证它已经看过文件。

复制下面的提示词:

我是 RIG-TARS 开发新手。当前工程来自 https://github.com/LuwuDynamics/rig_omni。
目标是 ESP32-S3 / RIG-Tars / Domestic (China),使用 ESP-IDF 5.5.3。
先读取 main/boards/tars/tars_board.cc,找到现有 InitializeTools()。
我的原版固件已经构建并运行正常。
只增加一句 Info 启动日志:My first TARS firmware is running。
如果已有这条练习日志,只修改它的文字,不再重复添加。
先说明插入位置;修改后展示最小 diff、测试步骤、预期结果和撤销办法。
不要改引脚、舵机 ID、零位、分区、依赖、账号信息或网络地址。
不要自动烧录、擦除或控制机器人运动。硬件操作由我确认端口后执行。
不确定的 API 先查当前工程,不要编造函数。

按 描述 → 看差异 → 编译 → 手动烧录 → 验证 → 保留或撤销 的顺序操作。手工加日志与 AI 加日志是同一个练习,做一次即可。下一次可只改日志中的昵称;不要在第一个改动还没验证时继续叠加动作和传感器功能。

9. 第一个 MCP 工具:只打印,不运动

MCP 工具是机器人向已连接的客户端提供的一项可调用功能。工具名用于识别功能,参数用于传值,回调函数在真正收到调用时执行。机器人回答“你好”并不能证明新工具运行了。

仍在 InitializeTools() 内,找到现有的 auto& mcp_server = McpServer::GetInstance();,在它后面加入:

mcp_server.AddTool(
    "self.robot.hello",
    "Run the hello test without moving the robot.",
    PropertyList(std::vector<Property>{}),
    [](const PropertyList&) -> ReturnValue {
        ESP_LOGI(TAG, "Hello tool called");
        return true;
    });
  1. 保留原工具注册代码,检查没有重复的 self.robot.hello,保存并重新编译、烧录。
  2. 让机器人恢复国内账号连接,重新建立对话或刷新客户端工具列表。
  3. 若界面提供工具调用入口,选 self.robot.hello,参数填 {},表示没有参数。
  4. 否则请求已连接的智能体“调用一次 self.robot.hello,并告诉我结果”。是否实际选用工具仍取决于客户端。
  5. 检查串口出现 Hello tool called。true 是调用结果,不是语音播放指令。

桌面 AI 客户端控制 RIG 时,应从自己设备的 MCP 设备控制设置复制配置;RIG 使用 HA 或电脑工具时,应使用智能体的 MCP 接入点。两种方向的配置不能混用。具体产品流程见桌面端网站。不要把 USB 串口号、机器人 IP 或 GitHub 地址当作 MCP 服务地址。

10. 直接使用 TARS 已有的工具

下列工具来自公开代码的 InitializeTools()。已有工具不要求先添加 hello 示例,但安装的固件和客户端必须实际提供对应工具。

工具名参数用途
self.tars.set_personalityhonesty、humor:整数 0–100;省略或 -1 表示保持该项更新屏幕底部人格值并保存。至少给一项新值。
self.tars.forward必填 speed:整数 -60…60;必填 time:整数 0…10000正值前进,负值后退。speed 是步态幅度,time 为毫秒。
self.tars.turn必填 speed:整数 -60…60;必填 time:整数 0…10000正值左转,负值右转。幅度和时间含义同上。
self.tars.calibrate必填 mode:整数 0 或 11 进入标定;0 尝试保存零位并结束。
self.ble.remote_control必填 enable:整数 0 或 11 开启蓝牙遥控模式,0 退出。

**先试不运动的操作:**调用 self.tars.set_personality,参数为:

{"honesty":90,"humor":80}

屏幕应显示 HONESTY 90% 和 HUMOR 80%,正常重启后保持。恢复默认值使用 {"honesty":90,"humor":75};只想改幽默度可将 honesty 设为 -1。这些数值会保存,但实际对话风格取决于智能体如何使用,不能把“诚实度”当成回答正确率。

再试一次短时运动

在完成标定的整机上,选择有足够空间的平整地面,一次只测一个请求:

  1. 调用 self.tars.forward,参数 {"speed":10,"time":500}。这是小幅度、500 毫秒的前进请求,不保证具体行走距离。
  2. 观察动作和串口 MCP forward speed=10 time=500。到时后步态停止;工具返回 true 表示接收请求,不表示物理动作已经完成。
  3. 显式停止前进或转向可调用 self.tars.forward,参数 {"speed":0,"time":0}。该函数会同时清掉转向幅度。停止步态会让关节目标回到零位附近,不等于舵机卸力。
  4. 前一步正常后,再用 self.tars.turn 和 {"speed":10,"time":500} 测试短时左转。

time=0 且 speed 非零表示持续运动,不是“运动零秒”。 初学者先用有限时长。新的前进指令会清掉转向幅度,新的转向指令会清掉前进幅度;这些接口不会自动排成路线。软件连接失效且发生意外运动时,使用实体电源开关停止。

代码中还注册了 self.laser.control,但 TARS 的 ControlLaser 实现已被注释。不能因为工具列表里有这个名字,就认为该版本能驱动激光硬件。

11. 找到正确的源码文件

文件实际职责
main/boards/tars/tars_board.cc初始化、按键与触摸、人格持久化、MCP 注册。
main/boards/tars/board_config.h电机 UART TX46/RX38、触摸 GPIO3 低有效、IMU SDA14/SCL48、横屏参数。先保持与实物匹配。
main/boards/tars/robot.cc零位读取/保存、首次标定与机器人任务。
main/boards/tars/robot_action.cc1.5 Hz 步态、前后运动、转向、限时停止。
main/boards/tars/motor.cc、motor.h三台 SCS009 的适配、反馈与堵转检测。共享协议见 main/boards/common/motors/。
main/boards/tars/tars_display.cc、tars_display.h320 × 240 ST7789V2 终端布局、实时状态和人格值。
main/boards/tars/320_240/、emoji/、wakenet/布局、动画和唤醒资源。
main/mcp_server.h、mcp_server.cc参数类型、工具注册和请求处理。
main/boards/tars/version.txtTARS 源码版本。

控制链可按 工具注册 → tars_set_forward / tars_set_turn → tars_gait_update → WritePos → 电机协议 阅读。先跟踪调用关系,再考虑修改步态。不要把旧教程中的 xgo.cc、xgo_action.cc 当成当前路径。

电机层有堵转检测,但不能保证任意动作、机械装配和参数都安全。首次练习保持舵机 ID、方向、零位、限幅和实时任务不变。

12. 修改声音和终端界面

换一段开机声音

先备份 main/boards/tars/tars_startup.ogg,用自己的或已授权的音频。在已安装 FFmpeg 的电脑上,从工程根目录执行:

ffmpeg -i my-startup.wav -t 4.5 -ac 1 -ar 16000 -c:a libopus -b:a 24k main/boards/tars/tars_startup.ogg
idf.py reconfigure
idf.py build

FFmpeg 会在覆盖现有文件前询问。先试听,再烧录成功构建的程序,正常重启并确认声音。板型 Ogg 音效会嵌入应用程序;新增一个文件名不会自动决定它在什么时候播放,还需要在对应事件中调用。增加或删除音频文件后重新 reconfigure。

仓库另提供 tools/generate_tars_voice_pack.py,供已有对应语音服务账号的开发者生成候选音效。输出在 tools/tars_voice_output/,试听后再替换板型目录文件,不会自动安装。用本地录音完成首次练习不需要语音服务账号。

修改终端前先分清显示来源

左侧 FLIGHT LOG 循环显示预设文本,不是故障事件记录;真实调试日志用串口监视器查看。右侧含实际状态、舵机相对零位角度、电量和 IMU 数据。NET 当前显示 CHG / ON / WAIT 电源状态,不代表网络连接状态。

可先修改 tars_display.cc 中一条装饰文本,编译后检查排版。保留标定错误提示和配网二维码流程。EAF 动画与打包的唤醒资源发生变化时,需要重新构建并烧录匹配的 assets;国内与国际固件区域对应各自服务和二维码。TARS 专用英文提示音在两个区域共用,不能单凭听到英文音效判断烧错了区域。

13. 版本查看与发布打包

个人首次开发使用 idf.py build / flash 即可,不必执行批量发布流程。

python tools/version.py list
python tools/version.py get tars
python tools/package_luwu_firmware.py --board tars --dry-run

--dry-run 只展示计划,不编译、不烧录。正式运行打包脚本还会构建独立的硬件测试固件,因此需要额外的 Test_Firmware/ 或 test_firmware/ 工程;当前公开仓库没有包含该独立工程。只构建机器人正式固件时继续使用 IDF 流程即可。

打包脚本默认输出到 releases/Luwu-Tools/bin/:国内版 RIG/tars/,国际版 RIG/tars/gb/,硬件测试版 GARAGE/tars/。不要把硬件测试固件当成日常使用固件。应用构建采用的版本可在 build/project_description.json 检查;源码版本不代表烧录平台已经发布同版本二进制文件。

遇到问题?按现象处理

现象如何处理
找不到 idf.py打开或重新激活已安装的 ESP-IDF 环境。
菜单里没有 RIG-Tars确认 ESP32-S3、项目目录及源码是否为当前公开版本;保留本地修改后更新。
原版编译失败看第一条相关错误,核对工具链和依赖下载;先不要叠加代码改动。
串口找不到或被占用检查数据线、实际端口、驱动、权限及其他串口程序。
烧录后二维码缺失或区域不对检查 RIG-Tars、Domestic、Emote animation style 和 Flash Emote Assets,重建并烧录配套程序与资源。
SERVO … NOT DETECTED某些舵机反馈未通过零位有效性检查。断电后检查接线、ID 1–3 和机械姿态,再检查反馈;提示本身不等于电机损坏。
FLASH ERASE FAILED / FLASH WRITE FAILED保存零位失败。记录串口错误、检查供电,持续发生时联系售后,不要先全片擦除。
标定工具返回 true,但还在 CALIB返回值只是调用确认;保存失败会显示红色错误并留在标定,需以屏幕和日志确认结果。
屏幕在长触摸后熄灭外置触摸保持至少 3 秒后松开会深睡眠,短触唤醒并重新启动。BOOT 长按是另一套功能。
hello 工具没出现或没日志确认新固件已烧录、设备在线、工具列表已刷新,并核对是否实际发出调用。
打包找不到 Test_Firmware缺少完整发布流程的额外工程;构建机器人本体使用 idf.py 即可。

标定模式之外,普通短触外置模块没有设置日常动作;不要把它当成通用对话按钮。标定失败时不要删除源码中的反馈检查来“强行通过”。

撤销修改,回到可用状态

只删除自己加入的日志行或 hello 注册块,检查 git diff,重新编译并烧录同板型、同区域。仅在编辑器里删掉代码不会改变机器人中已经运行的固件。

编译失败不会改变之前烧录的固件。若新固件启动异常,停止硬件测试,恢复上一份可用源码和配置;无法恢复构建时,使用国内烧录平台选择 中文 → RIG 系列 → RIG-TARS 的正式固件,之后重新核对标定、配网和对话。

**完成标志:**能构建原版、确认实际串口、看到自己的日志、保留正常功能,并知道如何恢复。如果做了 MCP 练习,还应看到真实调用日志,而不仅是听到口头回复。

代码依据:板型与菜单、TARS 板级与工具、标定、运动、发布脚本。