简介
要基于端到端实现一个有双臂的轮足机器人, 可以基于语音控制关灯,捡东西丢垃圾桶里,把地上的东西放桌子上,叠衣服等。
曹志伟
搭建并维护 Agent-VLA-LLM 解耦协作框架,实现 VLA 服务接口、配置管理、Git 协作流程和本地联调测试。同时负责采集机器人任务数据、训练 SmolVLA 模型,并将训练好的模型接入框架,实现捡球、关灯等桌面机器人技能的可扩展部署。
第一周
week1
一、框架核心工作
本周完成了桌面端机器人 Demo 第一版的整体技术框架设计与基础代码搭建。目标是构建一个可扩展、可替换、便于多人协作开发的 Agent + VLA + LLM 解耦框架,使上层 Agent 可以根据用户自然语言输入,选择调用具身智能模型或通用大语言模型。
框架目录位于:
/home/czw1/ChenLong-Robot-Internship/agent_vla
整体架构设计如下:
用户输入
|
v
Agent API
|
+-- 机器人任务 -> VLA Service -> SmolVLA / LeRobot / 后续 Ascend NPU
|
+-- 通用问答 -> LLM Service -> OpenAI / Ollama / 本地大模型
本周实现了三个核心服务:
-
Agent API- 作为系统统一入口,接收用户输入。
- 根据用户输入判断是机器人任务还是通用问答。
- 将机器人任务映射为固定的
skill_id,例如ball_pick_v1。 - 根据路由结果调用 VLA Service 或 LLM Service。
-
VLA Service- 负责管理机器人技能。
- 提供
GET /v1/skills和POST /v1/execute接口。 - 当前实现了
mockprovider 和lerobot_rolloutprovider。 - 后续可以新增
ascend_vlaprovider,用于 Orange Pi AI Pro / Ascend NPU 推理。
-
LLM Service- 负责通用语言模型能力。
- 提供
POST /v1/generate接口。 - 当前实现了
mockprovider。 - 后续可以扩展 OpenAI、Ollama、Qwen、本地大模型等 provider。
当前核心代码结构如下:
agent_vla/
configs/
app.yaml # 全局配置:路由规则、技能、模型路径、服务地址
src/
common/ # 共享 schema、配置读取、HTTP 工具
agent_api/ # Agent 入口、意图路由、工具调用
vla_service/ # VLA 服务和 provider
llm_service/ # LLM 服务和 provider
scripts/
run_agent_api.sh
run_vla_service.sh
run_llm_service.sh
run_mock_stack_test.sh
smoke_test.sh
docs/
architecture.md
contracts.md
development_plan.md
框架中的核心解耦点是 src/common/schemas.py。Agent、VLA、LLM 三部分统一使用这里定义的请求和响应结构,包括:
UserRequest
AgentResponse
ToolCall
VLAExecuteRequest
VLAExecuteResponse
LLMGenerateRequest
LLMGenerateResponse
通过这种方式,Agent 不需要关心 VLA 底层是 LeRobot、PyTorch、ONNX、CANN 还是 Orange Pi NPU;也不需要关心 LLM 底层是 OpenAI、Ollama 还是本地模型。只要接口协议不变,底层 provider 可以独立替换。
本周还完成了 mock 栈测试:
cd /home/czw1/ChenLong-Robot-Internship/agent_vla
bash scripts/run_mock_stack_test.sh
测试结果:
- 输入“帮我把球捡起来”可以正确路由到
robot.pick_ball,并调用 VLA Service。 - 输入
pick ball可以正确路由到robot.pick_ball。 - 输入“北京有什么旅游景点”可以正确路由到
llm.general_qa,并调用 LLM Service。
整体来看,第一版框架已经具备以下能力:
- Agent、VLA、LLM 三方解耦。
- 支持通过配置注册机器人技能。
- 支持通过 provider 替换 VLA 或 LLM 后端。
- 支持 dry-run,便于在不控制真实机械臂的情况下联调接口。
- 为后续 Orange Pi AI Pro / Ascend NPU 部署预留了扩展位置。
二、模型核心工作
本周完成了 LeRobot / SmolVLA 相关环境调试、硬件链路验证、数据采集参数设计和训练部署方案设计。
当前硬件与环境约定如下:
系统环境:WSL2 Ubuntu 24.04
Python 环境:conda env lerobot
机器人框架:LeRobot
具身模型:SmolVLA
从臂:SO101 follower,/dev/ttyACM0
主臂:SO101 leader,/dev/ttyACM1
摄像头:USB Camera,/dev/video0
已完成的硬件链路验证包括:
- SO101 follower 从臂可以正常连接。
- SO101 leader 主臂可以正常连接。
- 主从臂 teleoperation 可以跑通。
- USB 摄像头可以被 OpenCV 识别。
- SmolVLA 相关依赖和 GPU 训练环境可用。
摄像头调试过程中确认了一个关键参数:摄像头实际回报 FPS 为 30。如果在 LeRobot 配置中写成 fps=10,会出现校验错误:
OpenCVCamera(0) failed to set fps=10 (actual_fps=30.0)
因此后续摄像头配置统一固定为:
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 160, height: 120, fps: 30, fourcc: MJPG} }"
这里选择 160x120 是为了保证 WSL2 + USB 摄像头 + SmolVLA 推理链路足够稳定。摄像头硬件 FPS 使用 30,而数据集保存频率使用 --dataset.fps=10,两者不是同一个参数。
第一版 SmolVLA 任务定义为:
Pick up the ball and place it in the target area.
也就是桌面静态捡球并放到目标区域。当前设计的数据集名称为:
czw1/so101_ball_pick_v1
正式采集命令设计如下:
source /home/czw1/miniforge3/etc/profile.d/conda.sh
conda activate lerobot
cd /home/czw1/lerobot
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=follower \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 160, height: 120, fps: 30, fourcc: MJPG} }" \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=leader \
--dataset.repo_id=czw1/so101_ball_pick_v1 \
--dataset.single_task="Pick up the ball and place it in the target area." \
--dataset.fps=10 \
--dataset.episode_time_s=15 \
--dataset.reset_time_s=8 \
--dataset.num_episodes=60 \
--dataset.video=true \
--dataset.push_to_hub=false \
--display_data=false \
--resume=false
后续如果需要追加数据,保持同一个 dataset.repo_id,并将:
--resume=true
打开即可。
为了保证后续可迭代,本周还确定了数据集版本规则:
czw1/so101_ball_pick_v1 静态桌面捡球并放到目标区
czw1/so101_ball_pick_v2 增加球位置、光照、背景、起始姿态变化
czw1/so101_ball_handover_v1 人手递球,机械臂夹住后放置
czw1/so101_ball_roll_v1 慢速滚动球任务
czw1/so101_light_switch_v1 关灯任务
训练方面,由于当前只有一个真实摄像头,而 SmolVLA base 默认期望多个摄像头输入,因此训练时需要做两个处理:
--rename_map="{ observation.images.front: observation.images.camera1 }"
--policy.empty_cameras=2
其中 rename_map 用于把数据集中的 front 摄像头映射到 SmolVLA 期望的 camera1,empty_cameras=2 用于补齐另外两个空摄像头输入。
第一版训练命令设计如下:
source /home/czw1/miniforge3/etc/profile.d/conda.sh
conda activate lerobot
cd /home/czw1/lerobot
lerobot-train \
--policy.path=lerobot/smolvla_base \
--policy.repo_id=czw1/so101_ball_pick_smolvla_v1 \
--policy.push_to_hub=false \
--dataset.repo_id=czw1/so101_ball_pick_v1 \
--rename_map="{ observation.images.front: observation.images.camera1 }" \
--policy.empty_cameras=2 \
--batch_size=1 \
--steps=2000 \
--save_freq=500 \
--output_dir=outputs/train/so101_ball_pick_smolvla_v1 \
--job_name=so101_ball_pick_smolvla_v1 \
--policy.device=cuda \
--wandb.enable=false
如果效果不够,继续训练到 5000 steps:
lerobot-train \
--policy.path=lerobot/smolvla_base \
--policy.repo_id=czw1/so101_ball_pick_smolvla_v1 \
--policy.push_to_hub=false \
--dataset.repo_id=czw1/so101_ball_pick_v1 \
--rename_map="{ observation.images.front: observation.images.camera1 }" \
--policy.empty_cameras=2 \
--batch_size=1 \
--steps=5000 \
--save_freq=500 \
--output_dir=outputs/train/so101_ball_pick_smolvla_v1 \
--job_name=so101_ball_pick_smolvla_v1 \
--policy.device=cuda \
--wandb.enable=false \
--resume=true
部署测试方案使用 lerobot-rollout。考虑到当前链路推理速度较慢,先使用低频安全测试:
lerobot-rollout \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=follower \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 160, height: 120, fps: 30, fourcc: MJPG} }" \
--policy.path=/home/czw1/lerobot/outputs/train/so101_ball_pick_smolvla_v1/checkpoints/002000/pretrained_model \
--rename_map="{ observation.images.front: observation.images.camera1 }" \
--task="Pick up the ball and place it in the target area." \
--fps=1 \
--duration=15 \
--display_data=false \
--return_to_initial_position=false
这一部分的核心成果是:确定了第一版 SmolVLA 模型的任务、采集参数、训练参数、继续训练方式和部署测试方式,并且将这些参数与 agent_vla 框架中的 VLA Service 对接方式统一起来。训练完成后,只需要把 checkpoint 路径写入 configs/app.yaml,即可通过 Agent 调用 VLA 模型。
此外,本周还调研了可复用的“捡物块 / pick-place”基础模型方案。选择先从捡球、捡物块这类任务入手,主要是因为 pick-place 是桌面机器人最基础、最通用的动作单元,很多后续任务都可以拆解为类似能力:
捡球 -> 抓取物体 -> 移动到目标区域 -> 放下
放到桌子上 -> 抓取物体 -> 移动到桌面指定位置 -> 放下
整理桌面 -> 多次执行 pick-place
人手递物 -> 接近物体 -> 闭合夹爪 -> 移动到目标区
当前调研结论是:第一版不直接追求大而全的多任务模型,而是先训练一个稳定的 so101_ball_pick_smolvla_v1,把它作为可复用的桌面抓取基础模型。后续如果捡球效果稳定,再把数据扩展为更通用的捡物块模型,例如:
czw1/so101_pick_object_v1
该数据集可以逐步加入:
- 球
- 方块
- 小积木
- 轻量日用品
- 不同颜色和不同材质的小物体
对应的任务描述可以统一为:
Pick up the object and place it in the target area.
这样可以把模型从“只会捡球”扩展为“能捡常见小物体”,提高后续复用价值。对于 Agent 框架来说,这类能力可以注册成一个通用 VLA 技能:
pick_object_v1:
name: Pick up object
task_prompt: "Pick up the object and place it in the target area."
policy_path: /home/czw1/lerobot/outputs/train/so101_pick_object_smolvla_v1/checkpoints/...
后续 Agent 在理解用户指令时,可以把“捡球”“拿积木”“把这个东西放到目标区”等不同说法统一路由到同一个可复用的 pick_object_v1 技能,从而减少重复训练和重复开发成本。
三、下周主要工作
下周的主要目标是把当前框架从 mock 联调推进到真实模型闭环。
计划工作如下:
- 正式采集
czw1/so101_ball_pick_v1数据集,目标至少 60 条高质量演示。 - 使用 SmolVLA base 训练
so101_ball_pick_smolvla_v1,先训练 2000 steps。 - 使用
lerobot-rollout对捡球任务进行低频部署测试,统计基础成功率。 - 根据测试效果决定是否继续训练到 5000 steps 或补充采集数据。
- 将训练好的 checkpoint 路径写入
agent_vla/configs/app.yaml。 - 将 VLA Service 从
mockprovider 切换为lerobot_rolloutprovider。 - 让 Agent 通过
/v1/chat真实调用 VLA Service 执行捡球任务。 - 接入一个真实 LLM provider,例如 OpenAI、Ollama 或本地模型,用于替换当前 mock LLM。
- 优化 Agent 的意图识别方式,减少纯关键词匹配带来的误判。
- 在捡球任务稳定后,规划第二个技能,例如关灯或放到桌子上。
后续长期方向是将当前 WSL2 桌面端 Demo 逐步迁移到 Orange Pi AI Pro。初期可以让 Orange Pi 只运行 Agent,VLA 推理仍调用 WSL2 服务;等 SmolVLA 到 ONNX / Ascend NPU 的部署链路验证后,再新增 ascend_vla provider,使底层推理切换到 Orange Pi AI Pro / Ascend NPU,而 Agent 层接口保持不变。
week2工作
1.lerobot支持的 符合当前项目的具身模型
| 模型 | 是否LeRobot支持 | 参数规模 | 输入 | 输出 | 最大特点 | 训练方式 |
|---|---|---|---|---|---|---|
| SmolVLA | ✅ 官方重点支持 | 450M左右 | 图像 + 文本 + robot state | action chunk | 小模型、端侧友好、低成本微调 | Transformer + Action Expert,模仿学习 |
| OpenVLA | ✅ 可接入 | 7B | 图像 + 文本 | action token | 当前最经典开源VLA之一,泛化能力强 | 大规模机器人数据预训练 + SFT |
| Pi0 (π0) | ✅ 社区支持 | 3B左右 | 图像 + 文本 + proprioception | 连续动作 | Physical Intelligence提出,能力强 | Flow Matching + VLM |
openvla和pi0都需要云端训练且都需要更大的数据集来训练
2.本周尝试的开源数据集和开源模型
调研LeRobot生态中基于SmolVLA的开源模型与数据集,重点关注SO101平台上的双视角(top+wrist)视觉输入任务
| 名称 | 类型 | 机器人 | 任务功能 | 摄像头数量 | 摄像头配置 |
|---|---|---|---|---|---|
| lerobot/smolvla_base | 模型 | 通用 | 通用VLA基础模型 | 多camera | 任意 |
| lerobot/svla_so100_pickplace | 数据集 | SO100 | 方块抓取放置 | 2路 | top + side/up |
| lerobot/svla_so101_pickplace | 数据集 | SO101 | 方块抓取放置 | 2路 | top + wrist/side |
| faye7/so101-smolvla | 模型 | SO101 | Pick & Place | 2路 | 没说明 |
| AndrewNoviello/so101-smolvla | 模型 | SO101 | Pick & Place | 2路 | 没说明 |
| rtsmc/smolvla_box_in_bin_so101_test | 模型 | SO101 | 方块放入盒子 | 2路 | top + wrist |
复现 LeRobot / SmolVLA 后机器人动作异常(抽搐、不成功)原因分析:
- 摄像头视角不匹配:训练使用的 camera 数量、位置、视角和实际部署环境不同。
- 数据泛化不足:开源模型训练环境和自己的任务、物体、场景差异太大。
- 环境差异大:桌面背景杂乱,目前的演示视频基本都是在纯色背景下进行 环境杂乱可能要进行更多的后训练
解决方案:
1.重新采集机器人数据
- 使用leader-follower遥操作方式采集任务轨迹。
- 记录top摄像头和手腕摄像头图像。
- 同步记录关节角度、夹爪状态和执行动作。
2.构建自定义VLA数据集
- 输入:
- 多视角图像
- 机器人状态
- 文本任务描述
- 输出:
- action chunk(未来多个控制动作)
3.基于SmolVLA进行微调
- 使用官方450M SmolVLA作为初始化模型。
- 使用自己的SO101数据进行监督微调。
- 让模型学习机器人自身运动学和任务环境。
3.双臂场景的调研分析
| 场景 | 双臂分工 | 社区参考情况 |
|---|---|---|
| 双臂共同搬盒子 | 左右臂分别夹住盒子两侧,移动到目标区域 | 属于最基础的同步双臂控制任务,适合作为自采数据起点 |
| 一臂固定盒子,另一臂放入东西 | 左臂扶住容器,右臂抓取并放入 | 社区已有双臂抓取积木并放入箱子的 SmolVLA 训练案例。 |
| 双臂分别抓取物品并整理 | 两臂各抓一个物体,分别放入杯子或箱子 | 社区已有双 SO101 抓取马克笔并放入容器的 SmolVLA 模型 |
| 双臂传递方块 | 左臂拿起,右臂接住并放置 | 已有公开的双 SO100 方块交接数据集及 SmolVLA、π0、GR00T 等模型。 |
| 一臂打开盒盖,另一臂放物体 | 左臂拉住盒盖,右臂完成抓取放置 | 可由“开门”和“物体放入容器”两个已有社区任务组合而成,属于较实际的多阶段任务。 |
| 双臂搭简单金字塔 | 两臂交替拿积木,完成底层和上层摆放 | 已有基于约100条 episode 训练的双 SO101 SmolVLA 金字塔模型,但公开说明较少。 |
| 双臂展开或折叠毛巾 | 两臂抓住毛巾两角,拉平后折叠 | LeRobot 社区已有衣物折叠演示,ArmnetBench 也包含双 SO101 毛巾折叠任务。 |
| 双臂分类物体 | 左臂处理左侧物体,右臂处理右侧物体,按颜色放入不同区域 | 属于双臂抓取整理任务的自然扩展,适合使用不同文本指令训练多任务 SmolVLA |
初步定为左右手传递物品,双手传递相比单臂抓取放置:
扩大工作空间:一个机械臂抓不到或放不到的位置,可以通过另一只机械臂接力完成。
支持任务分工:左右机械臂可以分别负责取料和放置,形成连续的操作流水线。
减少单臂大范围运动:单臂不需要跨越整个桌面,能够缩短轨迹并降低碰撞风险。
第三周
week3
1.标准化部分调研以及模型数据集通用方法调研
本周补充调研了标准化方案。要求标准化的核心目标是:如果别人购买同样的 SO101 主从臂、同样的双摄像头和类似的桌面任务环境,可以尽量复用本项目的数据采集、训练和部署流程,而不是每个人都从零开始调设备、写命令、排查路径。
当前标准化计划分为硬件标准化、软件环境标准化、数据采集标准化、数据集格式标准化和模型训练标准化五部分。
1.1 硬件标准化
硬件标准化的目标是固定机器人和传感器组合,减少由于设备差异导致的模型不可复用问题。
| 标准化项目 | 当前约定 | 作用 |
|---|---|---|
| 机械臂 | SO101 leader + SO101 follower | 保证动作空间、关节数量和控制方式一致 |
| 摄像头数量 | 2 路 | 保证视觉输入结构一致 |
| 摄像头视角 | overhead + wrist | 保证训练和部署时的视觉分布一致 |
| 任务物体 | tennis ball | 固定第一阶段任务对象 |
| 任务目标 | target area | 固定放置区域定义 |
后续如果其他同学购买同样硬件,只需要按照同样的机械臂型号、摄像头数量、摄像头位置和任务场景搭建,即可复用本项目的数据采集脚本和训练配置。
1.2 软件环境标准化
软件标准化主要解决“同一套命令在不同电脑上跑不起来”的问题。当前项目环境约定如下:
Ubuntu 22.04
Python 环境:conda env lerobot
机器人框架:LeRobot 0.5.2
采集命令:lerobot-record
训练命令:lerobot-train
数据格式:LeRobotDataset
需要标准化保存的内容包括:
- conda 环境名称和依赖版本。
- LeRobot 版本。
- 数据采集命令模板。
- 训练命令模板。
1.3 数据采集标准化
数据采集标准化的目标是让不同人采集的数据具有相同结构,后续可以合并训练。
当前任务文本统一为:
Pick up the tennis ball and place it in the target area.
当前 camera key 统一为:
overhead
wrist
这两个名称后续需要固定,不能一批数据叫 top,另一批叫 front,否则训练时模型输入字段不一致,会影响数据集合并和模型加载。
建议后续采集标准如下:
| 项目 | 建议标准 |
|---|---|
| episode 时长 | 30s |
| reset 时长 | 10s |
| 数据集 FPS | 优先 15fps,稳定后再尝试 30fps |
| 任务文本 | 固定英文任务描述 |
| 数据目录 | 使用时间戳,避免覆盖 |
| 失败样本 | 单独记录并剔除 |
| 摄像头 key | 固定为 overhead 和 wrist |
标准化采集的意义是:后续如果其他人用同样硬件采集同一任务,可以把数据直接合并到同一个 LeRobotDataset 训练流程中,而不需要重新写数据转换代码。
1.4 数据集格式通用性调研
LeRobot 的核心优势是数据集格式相对统一。通过 lerobot-record 采集的数据会保存为 LeRobotDataset,其中包括:
- 多路图像 observation。
- 机器人 state。
- 机器人 action。
- episode 信息。
- 任务文本
task。 - 数据集 meta 信息。
只要模型支持 LeRobotDataset,就可以在同一套数据上切换不同 policy 做实验。也就是说,本项目采集的数据不只服务于 SmolVLA,也可以用于对比其他 imitation learning 或 VLA 模型。
1.5 标准化交付计划
为了让其他人购买同样硬件后可以复用,本项目后续计划整理一套标准化交付材料:
1. 硬件清单
2. 摄像头安装位置示意
3. LeRobot 环境安装说明
4. USB attach 脚本
5. 主从臂校准步骤
6. 双摄像头采集命令模板
7. LeRobotDataset 检查脚本
8. SmolVLA / ACT / Diffusion 训练命令模板
9. rollout 测试步骤
10. 常见错误排查表
标准化的最终目标是形成一套可以复制的 SO101 双摄像头 VLA 数据采集和训练流程。
2.训练模型部分
模型训练部分当前主要围绕自采 LeRobotDataset 展开。数据采集完成后,同一套数据集可以优先用于以下三类实验:
-
**SmolVLA **
- 作为主线模型。
- 使用双摄像头图像、机器人状态和文本任务描述。
- 目标是训练可执行 “Pick up the tennis ball and place it in the target area.” 的 VLA 策略。
-
**Pi0 **
-
作为更大模型方向储备。
-
需要更多算力和更稳定的数据集。
-
当前不作为第一优先级。
-
因此当前采集数据时,需要尽量保证数据字段通用:
camera keys: overhead, wrist
task: Pick up the tennis ball and place it in the target area.
robot type: so101_follower
teleop type: so101_leader
fps: 15 或 30,但同一批数据内保持一致
这样后续可以在不重新采集数据的情况下,直接切换 --policy.type=smolvla、--policy.type=act 或 --policy.type=diffusion 进行训练对比。
本周训练的采集数据遇到的硬件问题:
问题 1:摄像头 FPS 设置失败
采集过程中出现过摄像头帧率设置失败:
OpenCVCamera(...) failed to set fps=15 (actual_fps=30.0)
原因是部分 USB 摄像头实际只支持固定的 30fps 模式。即使在 LeRobot 配置中请求 15fps,驱动仍返回 30fps。LeRobot 会严格检查请求帧率和实际帧率是否一致,因此直接报错退出。
处理方式:
- 对实际只能 30fps 的摄像头,在摄像头配置中写
fps=30。 - 如果希望数据集帧率更低,可以通过
--dataset.fps=15控制保存频率。 - 不强行把所有摄像头都设置为 15fps。
结论:摄像头采集帧率和数据集保存帧率可以分开考虑。摄像头按硬件支持的模式运行,数据集按训练需要保存。
问题 2:MJPG 坏帧
采集过程中频繁出现:
Corrupt JPEG data: premature end of data segment
这是 OpenCV 解码 MJPG 图像流时打印的警告,说明摄像头传来的 JPEG 压缩帧不完整。该问题在 WSL2 + USB 摄像头环境中比较常见,尤其是在双摄像头同时采集时更明显。
原因分析:
- MJPG 本质是连续 JPEG 压缩帧。
- USB 转发过程中如果数据包不完整,OpenCV 会收到不完整 JPEG。
- 双摄像头同时采集会增加 USB 带宽压力。
- WSL2 的 USB 转发稳定性弱于原生 Linux。
处理方式:
- 对不稳定的俯视摄像头,尽量避免使用 MJPG,改用 YUYV。
- 对手腕摄像头保留 MJPG,但降低分辨率到 320x240。
- 降低数据集保存帧率到 15fps。
- 尽量不要让两个摄像头插在同一个 USB Hub 上。
结论:少量 Corrupt JPEG data 可以忍受,但如果伴随读帧超时,就必须降低负载或更换摄像头格式。
问题 3:读帧超时
双摄像头采集过程中还出现过更严重的错误:
TimeoutError: OpenCVCamera(...) latest frame is too old
该错误会导致 LeRobot 停止录制。它说明某一路摄像头长时间没有提供新帧,超过了 LeRobot 的最大等待时间。
从日志看,主要不稳定的是俯视摄像头:
usb-Sonix_Technology_Co.__Ltd._USB2.0_CAM1...
原因分析:
- 俯视摄像头在 MJPG 模式下容易出现坏帧。
- 双摄像头同时 30fps 会使 WSL2 USB 转发压力较大。
- 实时视频编码会进一步增加 CPU 压力。
- 当采集主循环低于目标 FPS 时,图像缓存中的最新帧可能变旧,最终触发 timeout。
处理方式:
俯视摄像头:YUYV,640x480,15fps
手腕摄像头:MJPG,320x240,30fps
数据集保存:15fps
实时编码:关闭
结论:由于任务要求必须使用两路摄像头,当前不能简单改成单摄像头采集。较可行的方案是降低双摄像头整体负载,并让俯视摄像头避开不稳定的 MJPG 模式。
问题 4:采集循环低于目标 FPS
日志中多次出现:
Record loop is running slower than the target FPS
这说明 LeRobot 的主循环速度低于设定的数据集 FPS,可能导致丢帧或机器人控制不稳定。
原因分析:
- 双摄像头读取耗时较高。
- 图像写盘线程占用 CPU。
- 视频编码占用 CPU。
- WSL2 文件系统和 USB 转发都有额外开销。
处理方式:
- 将
--dataset.fps从 30 降到 15。 - 关闭
--dataset.streaming_encoding。 - 减少
--dataset.num_image_writer_threads_per_camera。 - 降低手腕摄像头分辨率。
- 采集时关闭不必要的后台程序。
结论:当前WSL2 环境下,双摄像头 30fps 采集不够稳定,硬件适配问题严重
目前已更换ubuntu原生电脑来重新采集数据
第四周
week4 工作周报
1. SO101 网球放置数据集采集与整理
本周主要完成了 SO101 主从臂数据采集环境的重新整理,并基于真实机械臂采集了网球抓取放置任务数据。任务目标是让 follower arm 根据 leader arm 的遥操作轨迹,完成“捡起网球并放到目标区域”的操作。
本周采集任务英文指令统一为:
Pick up the tennis ball and place it in the target area.
当前数据集已整理为 LeRobot v3.0 格式,并上传到 Hugging Face,并做了详细的当前的内容的可复现工作整理 目标是该仓库是可被别人用相同的硬件直接复现的:
https://huggingface.co/datasets/vvzc/ChenLong_Embodied_Intelligence_Dataset
1.1 当前数据集规模
| 项目 | 当前数值 |
|---|---|
| 数据格式 | LeRobot v3.0 |
| 机器人类型 | so_follower |
| 总 episodes | 48 |
| 总帧数 | 21187 |
| 任务数量 | 1 |
| 采集帧率 | 30 FPS |
| 图像分辨率 | 640 x 480 |
| 摄像头数量 | 2 |
| 动作维度 | 6 |
| 状态维度 | 6 |
| 数据划分 | train: 0:48 |
数据集包含两个视觉输入:
observation.images.overhead
observation.images.wrist
其中 overhead 是俯视摄像头,用于观察桌面整体布局、网球位置和目标区域;wrist 是手腕摄像头,用于观察夹爪附近的抓取细节。
1.2 数据字段
当前数据集主要字段如下:
| 字段 | 类型 | 形状 | 含义 |
|---|---|---|---|
action | float32 | [6] | 主臂遥操作产生的动作目标 |
observation.state | float32 | [6] | 从臂当前关节状态 |
observation.images.overhead | video | [480, 640, 3] | 俯视摄像头视频 |
observation.images.wrist | video | [480, 640, 3] | 手腕摄像头视频 |
timestamp | float32 | [1] | 当前帧时间戳 |
frame_index | int64 | [1] | episode 内帧编号 |
episode_index | int64 | [1] | episode 编号 |
index | int64 | [1] | 全局帧编号 |
task_index | int64 | [1] | 任务编号 |
action 和 observation.state 的 6 个关节顺序为:
shoulder_pan.pos
shoulder_lift.pos
elbow_flex.pos
wrist_flex.pos
wrist_roll.pos
gripper.pos
1.3 采集硬件与端口
本周使用一台原生 Ubuntu 电脑重新配置采集环境,避免之前 WSL2 下 USB 摄像头转发不稳定的问题。
当前硬件配置:
| 设备 | 作用 | 当前端口 |
|---|---|---|
| SO101 follower arm | 从臂,实际执行动作 | /dev/ttyACM0 |
| SO101 leader arm | 主臂,人工遥操作输入 | /dev/ttyACM1 |
| overhead camera | 俯视摄像头 | /dev/video4 |
| wrist camera | 手腕摄像头 | /dev/video2 |
主从臂电机环境检查结果:
motor ids: 1, 2, 3, 4, 5, 6
baud rate: 1000000
model: 777
说明换臂后电机 ID、波特率和 SO101 默认配置一致,不需要重新写电机 ID,只需要重新完成机械臂校准。
1.4 采集参数与复现命令
本周最终固定的数据采集参数为:
| 参数 | 数值 |
|---|---|
| 每次采集条数 | 10 episodes |
| 单条采集时间 | 15 秒 |
| 每条 reset 时间 | 10 秒 |
| 采集 FPS | 30 |
| 视频分辨率 | 640 x 480 |
| 视频编码 | AV1 |
| 是否追加数据集 | --resume=true |
每次追加采集 10 条数据时使用的脚本为:
~/so101_record_tennis_append10.sh
脚本内部核心命令如下:
lerobot-record \
--robot.type=so101_follower \
--robot.port="/dev/ttyACM0" \
--robot.id="so101_follower_sakura" \
--robot.cameras="{overhead: {type: opencv, index_or_path: /dev/video4, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: /dev/video2, width: 640, height: 480, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port="/dev/ttyACM1" \
--teleop.id="so101_leader_sakura" \
--display_data=true \
--dataset.root="/home/sakura/lerobot_data" \
--dataset.repo_id="local/so101_tennis" \
--dataset.single_task="Pick up the tennis ball and place it in the target area." \
--dataset.fps=30 \
--dataset.episode_time_s=15 \
--dataset.reset_time_s=10 \
--dataset.num_episodes=10 \
--dataset.video=true \
--dataset.push_to_hub=false \
--dataset.streaming_encoding=true \
--dataset.encoder_threads=2 \
--resume=true
其中 --resume=true 是关键参数,用于在已有数据集后继续追加采集,避免覆盖已有 episode。
2. 数据集发布与说明文档完善
本周还整理并上传了数据集说明文档。README 中补充了硬件配置、端口映射、采集参数、字段结构、读取方式和复现命令,使其他人拿到相同 SO101 主从臂和双摄像头后,可以按照文档重新搭建采集流程。
README 中重点说明了:
- follower arm 和 leader arm 的作用区分。
- 双摄像头字段命名必须固定为
overhead和wrist。 - episode 采集时间为 15 秒,reset 时间为 10 秒。
- 数据集字段需要保持
observation.images.overhead、observation.images.wrist、observation.state和action一致。 - 追加采集时必须使用
--resume=true。
这一步的意义是把能在本机跑通”的流程转化为别人可以复现的数据集交付材料。
3. SmolVLA 模型训练
在数据集采集完成后,本周使用当前 SO101 网球放置数据集对 SmolVLA 进行了微调训练。训练在 WSL2 的 Ubuntu-24.04 中完成,使用 lerobot conda 环境。
训练完成后的模型位置为:
/home/czw1/lerobot/outputs/train/smolvla_chenlong_2000steps_run1/checkpoints/002000/pretrained_model
训练日志位置为:
/home/czw1/lerobot/training_logs/smolvla_chenlong_2000steps_run1.log
3.1 训练结果
| 项目 | 结果 |
|---|---|
| policy 类型 | smolvla |
| 训练步数 | 2000/2000 steps |
| 最终 loss | 0.116 |
| 输入视觉特征 | observation.images.overhead, observation.images.wrist |
| 输入状态特征 | observation.state |
| 输出特征 | action |
| 最终模型文件 | model.safetensors |
| 模型文件大小 | 约 907 MB |
| 训练总输出目录大小 | 约 5.0 GB |
| 训练进程状态 | 已结束,无残留训练进程 |
这次训练说明当前自采 LeRobotDataset 已经能够被 SmolVLA 正常识别和加载,双摄像头图像、机器人状态和动作输出字段也已经和模型输入输出对齐。
3.2 本次训练的意义
本次训练完成后,项目从“采集数据”推进到了“用自采数据微调 VLA 模型”的阶段。相比直接使用社区公开 SO101 模型,本次训练使用的是当前实验环境中的真实摄像头视角、真实桌面背景、真实网球和目标区域,因此模型更贴近实际部署环境。
本次训练验证了以下内容:
- 自采数据集的 schema 可以被 LeRobot 训练流程读取。
- 双摄像头输入可以进入 SmolVLA 模型。
observation.state与action字段维度正确。- 训练可以完整跑到 2000 steps。
- 输出 checkpoint 可以保存为可复用的
pretrained_model目录。
下周计划重点从训练完成转向模型验证和数据质量提升:
- 使用训练得到的 SmolVLA checkpoint 做真实机械臂 rollout 测试。
- 观察模型是否能够根据
Pick up the tennis ball and place it in the target area.完成闭环动作。 - 根据失败案例补采数据,例如抓取偏差、放置偏差、夹爪闭合不稳定等情况。
- 尝试扩大数据集规模,从 48 条增加到 100 条以上。
- 对比不同训练步数下的 checkpoint 表现,例如 2000 steps、5000 steps 和更长训练。
- 继续完善标准化文档,让其他同学可以按同样流程复现 SO101 数据采集、训练和部署。
宋红
AgentOS 编排层 / 端侧语言规划 / SimCar 反馈闭环
基本信息
| 项 | 内容 |
|---|---|
| 姓名 | 宋红 |
| 方向 | 意图理解、任务规划、指令下发、反馈闭环、失败处理、语音入口 |
| 项目 | 嘲风桌面机器人 AgentOS |
| 主代码 | agent-llm-vla/src/agent_api/ |
| SimCar 探索 | /root/chaofeng/.claude/worktrees/simcar-agent-loop/agent-llm-vla |
| 周期 | 2026-07-07 ~ |
文档入口
- AgentOS 编排层:启动期架构设计和职责说明;
- 当前实现状态:当前代码、测试、能力边界和下一步;
- 周报:按周汇总工作、证据和计划;
- 工作日志:从项目日志中筛选的关键实施与决策记录;
- 总览:项目设计、工程约束和协作边界;
- SimCar:Gateway、契约、演示、端侧 Planner 和交接资料;
- 资料索引:复制来源和选取理由。
最新进展
截至 2026-07-24:
- AgentOS / SimCar 已从单句指令推进到有界多轮会话:可记录场景障碍物、安全补全“绕过去”等指代,并在纯观察话轮中零动作落盘;
- 新增 L1 确定性快速路径、36 条规划基准与 raw/final 双口径门禁;当前
demo_gate_pass=true、model_gate_pass=false; - 落地
SIMCAR_REHEARSAL=1离线预演,以及 WSLg 实时麦克风 / 虚拟麦克风回放闭环;权威回归355 passed / 10 skipped; - 按老板要求启动 Ascend 310B / Orange Pi AIpro 20T 的 SenseVoice 端侧部署:板端已连通,ONNX 已导出,OM 转换阻塞在工具链算子包,持续推进中。
能力边界
当前已验证的是自然语言路由、端侧结构化计划、已知几何控制、有界会话上下文、离线预演和本机实时语音闭环。当前尚未完成真实视觉障碍物识别、未知环境自主导航、任意抽象轨迹、GPT 级开放指令理解,以及 310B 上可交付 OM / 板端 SenseVoice 推理。
涉及运动的系统坚持:大模型做高层语义和任务拆解;距离、角度、路径、安全边界和急停由确定性模块负责。
当前周报
原始资料位置
- 工作日志:
D:\THU\BeiJing\嘲风\工作日志\; - 总览:
D:\THU\BeiJing\嘲风\总览\; - 本目录中的副本用于个人工作归档,原始资料仍是跨团队权威来源。
AgentOS 编排层
宋红 · AgentOS 编排层技术文档 代码位置:
agent-llm-vla/src/agent_api/配套约束:D:\THU\BeiJing\嘲风\AgentOS任务约束手册.md
一、职责定位
AgentOS 编排层是“嘲风“桌面机器人的决策中枢,负责:
| 能力 | 现状 | 待补 |
|---|---|---|
| 意图识别 | 关键词硬匹配(28行) | 语义/LLM 分类,支持说法多样化 |
| 指令下发 | 已有 VLAClient.execute_skill() | 复用,不重写 |
| 环境交互反馈 | 无 | 解析执行状态 + 视觉判定任务成败 |
| 失败检测与重试 | 无 | 编排状态机:DISPATCH→EXECUTE→JUDGE→RETRY/REPORT |
| 多轮会话 | 无(session_id 仅透传) | 维护 session 上下文 |
核心文件:
router.py— 意图识别与工具路由(主战场)main.py— Agent 服务入口与编排流程tool_clients.py— 调用 VLA/LLM 服务的客户端
二、系统架构
┌─────────────┐
│ 用户语音/文本 │
└──────┬──────┘
│
┌──────▼──────┐
│ ASR 模块 │ SenseVoice-Small (254MB, CER~8%)
│ (音频→文本) │
└──────┬──────┘
│
┌──────▼──────┐
│ Agent API │ ← 我的主战场 (8010端口)
│ 编排状态机 │
└──┬──────┬───┘
│ │
┌──────────▼┐ ┌▼──────────┐
│ VLA Service│ │ LLM Service│
│ (8011端口) │ │ (8012端口) │
└──────┬─────┘ └───────────┘
│
┌──────────┼──────────┐
│ │ │
┌────▼────┐ ┌──▼───┐ ┌───▼────┐
│机械臂(VLA)│ │底盘(Nav)│ │视觉判定 │
│ 同学A │ │ 同学B │ │(YOLO等)│
└─────────┘ └──────┘ └────────┘
三服务解耦架构(已跑通):
- Agent API: 8010 — 编排中枢
- VLA Service: 8011 — 视觉语言动作(机械臂技能)
- LLM Service: 8012 — 大语言模型(通用问答)
三、编排状态机(方案02,已审核通过)
DISPATCH(意图识别)
│
├─ 安全检查:置信度 < 0.75 → REPORT_FAIL
│
▼
EXECUTE(调用执行)
│
├─ dry-run 预演 → 碰撞/边界检查
│
▼
JUDGE(视觉判定)
│
├─ 成功 → DONE
│
└─ 失败 → RETRY(≤ max_retries 次)
│
└─ 超限 → REPORT_FAIL → TTS 报告
关键设计决策:
- router 只做纯决策:
(intent, ToolCall)输出签名不变,下游零改动 - orchestrator 管执行编排:抽成独立
orchestrator.py,main.py 保持薄 - MockJudge 走 metadata 注入:smoke_test 可覆盖“一次过“与“失败重试“两条路径
- Judge 契约:
{success, detail, evidence},mock 阶段 evidence 恒{}
四、两个下游黑盒
| 下游 | 负责人 | 我下发什么 | 我不关心什么 |
|---|---|---|---|
| 机械臂(VLA) | 同学A | skill_id(如 ball_pick_v1) | 手臂怎么动 |
| 底盘移动 | 同学B | 高层路径/路线命令 | 轮子怎么驱动 |
路线规划是自有模块(route_planner):高层路线决策归我,轮子低层电机驱动归同学B。复合任务中 orchestrator 交替调度 VLA 和底盘。
五、技术选型
| 组件 | 选型 | 理由 |
|---|---|---|
| ASR | SenseVoice-Small (254MB) | 中文 CER~8%,20x 实时,纯 CPU |
| 意图识别(规则层) | 文本归一化 + 扩充同义词 | mock 阶段即见效 |
| 意图识别(LLM兜底) | Qwen2.5-1.5B/3B | 默认关闭,预留插槽 |
| 视觉判定(简单) | YOLO-small | 本地 CPU 实时,灯灭/球进桶 |
| 视觉判定(语义) | 云端 VLM | 叠衣服整齐度等,低频 |
| 边缘部署 | 昇腾310B (4GB) → K3 (8GB) | 310B 先演示,K3 后落地 |
| 推理后端 | llama.cpp + CANN/Q4_K_M | 社区成熟,310B 适配 |
六、开发阶段规划
第一月(mock): S1 ✅ → S2 → S3 → S4 → S5 → S6
第二月(仿真): S7 真实VLA仿真 → S8 本地LLM决策脑 → S9 关灯闭环
进阶: S10 边缘部署 → S11 决策引擎Phase3 → S12 MCP/SSE/多轮
路线规划(SR): SR1 接口占位 → SR2 骨架 → SR3 复合任务状态机
当前进度:S1 已完成,方案02(S2-S4)已 PASS,待进入 EXECUTE。
七、约束与红线
- 不破坏三服务解耦架构
- 不破坏
schemas.py契约(只允许向后兼容新增) - 不改 VLA/LLM 同事的 provider 内部代码
- 不在 agent 层 import lerobot / 绑定具体大模型 SDK
- 真机动作前必须 dry-run;危险动作需安全确认
- commit/PR 只署名本人,不添加任何 AI 共同署名
详见 D:\THU\BeiJing\嘲风\AgentOS任务约束手册.md。
当前实现状态(2026-07-18)
宋红 · AgentOS 编排层 / SimCar 端侧探索 资料入口:
D:\THU\BeiJing\嘲风\工作日志\26-当前项目与总览资料联合进度盘点-2026-07-17.md
一、当前基线
| 项目 | 状态 |
|---|---|
| AgentOS 集成分支 | integration/agentos-20260717 已验证 |
| SimCar 探索分支 | feat/simcar-agent-loop |
| SimCar worktree | /root/chaofeng/.claude/worktrees/simcar-agent-loop/agent-llm-vla |
| 最新提交 | 55d45ac |
| 全量测试 | 277 collected / 267 passed / 10 skipped / 0 failed |
| 模拟器修改 | 无 |
vla_service/** 修改 | 无 |
| push | 未执行 |
二、已经具备的端侧能力
2.1 语言与编排
- 中文文本输入;
- SenseVoice 音频文件转写入口;
- 关键词、动作-对象信号和否定拦截;
- Ollama/Qwen 高层 Planner 接口;
TaskPlan/TaskStep结构化计划;- Orchestrator 的执行、Judge、重试和终态契约;
- 结构化 attempt 日志。
2.2 SimCar 控制
- 前进、后退、左右转、停车;
- 单段平移不超过 5 cm;
- 单次运动距离和转角上限;
- 每段动作后读取位姿;
- 碰撞、断连和超时 fail closed;
hasBall=true + armState=holding的真值捡球判定。
2.3 复合任务 MVP
端侧 Planner 允许以下技能:
move
turn
stop
navigate_around
pick_ball
在障碍物坐标、尺寸和安全间距已经配置的前提下,可以执行:
绕过已知障碍物,把球捡起来
当前绕障来源是 known_scene_geometry,不是相机视觉。未知障碍物或“这个”无法唯一 grounding 时,不会发出移动命令。
三、语音和端侧推理现状
3.1 已确认
- WSLg 已暴露
unix:/mnt/wslg/PulseServer; - WSLg 目录中存在
PulseAudioRDPSource,具备向 WSL 提供音频源的基础条件; - SenseVoice provider 已经能够处理 WAV 文件;
/root/.ollama中已有qwen2.5:1.5b模型文件;- Runner 已支持文本和
@audio /absolute/path.wav。
3.2 尚未完成
- Ubuntu 用户态尚未安装
pactl、parec/arecord等采集工具; - 当前入口是“录音文件→识别”,不是实时麦克风流;
- 还没有 VAD、分片上传、实时 partial transcript、打断和急停通道;
- Ollama daemon 需要显式启动并完成一次 Planner 实测;
- 尚未决定是 WSLg 直接采集还是 Windows/浏览器采集后推送到 WSL。
推荐顺序:先用 WSLg PulseAudio source 验证 16 kHz 单声道录音,再加 200~500 ms 音频分片和 VAD,最后将 partial transcript 接入 Planner;急停单独走本地确定性通道,不等待 LLM。
四、抽象轨迹能力边界
当前 Planner 还不是 GPT-5.6 级的任意抽象轨迹执行器。对于:
走个正方形
系统不应该让 1.5B 模型随意猜边长。正确实现方式是新增高层技能,例如:
{
"skill": "trace_shape",
"arguments": {
"shape": "square",
"side_cm": 20,
"direction": "left"
}
}
其中 side_cm 可以来自用户明确表达,也可以来自配置的安全默认值;若没有默认值则进入澄清。trace_shape 内部再编译成四段平移和四段 90° 转向,并在每段后读状态。
后续应按以下等级扩展:
- L1:平移、旋转、速度、持续时间、急停;
- L2:正方形、长方形、圆形、等边三角形;
- L3:S 型、8 字、已知障碍物绕行、窄通道、返回起点;
- L4:全局路径、局部避障、找球、抓球和多步任务调度。
五、真实能力边界
已经在线验证的是:准备好的无障碍 SimCar 场景中,真值状态驱动的自动捡球闭环。
尚未证明的是:
- 通过摄像头识别任意可乐瓶或障碍物;
- 对“前面那个”进行视觉 grounding;
- 未知环境下自主建图和导航;
- GPT-5.6 级任意抽象指令的一次性可靠执行。
六、下一步验收门槛
- 安装并验证 WSLg 音频采集工具;
- 启动 Ollama,记录 Qwen 1.5B 对基础动作、规则图形和复合任务的计划成功率;
- 新增
trace_shape及其 Schema、动作编译器和安全测试; - 将实时语音入口拆成“识别流”和“动作流”,支持急停优先;
- 在 SimCar 中建立带障碍物坐标的确定性场景,完成一次真实绕障 live 验收;
- 1.5B 若在结构化计划、指代和抽象轨迹上不稳定,再比较 3B/7B 端侧模型,不先把低层安全交给模型。
资料索引(2026-07-18)
本目录保留宋红负责的 AgentOS、端侧 Planner、语音入口和 SimCar 闭环资料。复制件用于个人工作归档和周志引用,不替代原始目录中的跨团队权威文档。
工作日志
| 文件 | 选取理由 |
|---|---|
05-意图识别LLM兜底路由.md | 端侧小模型意图分类设计来源 |
23-S5B真实SenseVoice...md | 真实语音入口和演示证据 |
24-会话幻象核查与磁盘真相盘点...md | WSL/UNC 文件一致性和验收方法 |
25-老师全框架复用评估与项目设计定稿...md | 架构复用和职责边界定稿 |
26-当前项目与总览资料联合进度盘点...md | 2026-07-17 权威进度、SimCar 判断和测试数字 |
原始路径:D:\THU\BeiJing\嘲风\工作日志\。
总览
| 文件 | 选取理由 |
|---|---|
01-项目大纲.md | 项目入口和总体架构 |
03-项目完整规划.md | 分阶段实现方式和技术取舍 |
04-Agent执行约束.md | Schema、provider、安全和提交约束 |
06-工程落地方案.md | Orchestrator/Judge 工程契约 |
框架复用度全面分析.md | 已有模块复用和缺口判断 |
AgentOS编排层-项目设计与推进计划.md | 当前正式推进路线 |
新同学任务规划.md | World Model/视觉等协作边界 |
原始路径:D:\THU\BeiJing\嘲风\总览\。
SimCar
| 文件 | 内容 |
|---|---|
HANDOFF-2026-07-17.md | 分支、提交、测试、live 验收和能力边界 |
architecture.md | Agent/VLA/LLM/Judge/ASR 架构 |
contracts.md | 服务接口和 Schema 契约 |
development_plan.md | 原始开发阶段 |
simcar_demo.md | 无障碍真值捡球演示 |
simcar_agent_planner.md | 端侧 Qwen、已知几何绕障和统一 Runner |
原始路径:/root/chaofeng/.claude/worktrees/simcar-agent-loop/agent-llm-vla/。
更新规则
- 原始资料发生实质更新后,再同步副本;
- 周报引用明确的测试、提交或 live 结果,不用计划代替完成证据;
- 已知几何、模拟器真值和真实视觉必须分别表述;
- 文档出现冲突时,以实时 Git 状态、清缓存后的测试和原始权威文档为准。
第 1 周(2026-07-07 ~ 2026-07-09)
宋红 · AgentOS 编排层 · 暑期实习第一周 阶段声明:第一月(mock) 详细记录:
D:\THU\BeiJing\嘲风\任务日志.md+任务详情.md
一、本周工作总览
| 日期 | 阶段 | 工作内容 | 状态 |
|---|---|---|---|
| 07-07 | 阶段0 | 项目熟悉与任务约束建立 | ✅ 完成 |
| 07-07 | 阶段1 | mock 栈环境配置与联调验证 | ✅ 完成 |
| 07-07 | 阶段2 | 技术选型调研与整体计划确认 | ✅ 完成 |
| 07-08 | 阶段2 | 依据审核结果01进行整改 | ✅ 完成 |
| 07-08 | 阶段2 | 开发方案独立归档并编号 | ✅ 完成 |
| 07-08 | 阶段3 | 产出方案02(编排核心增强) | ✅ 完成 |
| 07-08 | 阶段3 | 依据审核02优化方案02 | ✅ 完成 |
| 07-09 | 阶段3 | 产出总览四件套文档 | ✅ 完成 |
| 07-09 | 阶段3 | 边界澄清:双下游黑盒 + 路线规划 | ✅ 完成 |
二、关键成果
2.1 环境搭建与联调验证
- WSL2 Ubuntu-24.04 + venv 隔离环境(fastapi/uvicorn/pydantic/pyyaml)
- 三服务(Agent:8010 / VLA:8011 / LLM:8012)mock 栈联调全通过
- smoke_test 四项测试全过:
/health→ ok- “帮我把球捡起来” →
robot.pick_ball→ball_pick_v1(中文命中) - “pick ball” → 同技能(英文命中)
- “北京有什么旅游景点” →
llm.general_qa(LLM 兜底)
- 修复 WSL 挂载导致的脚本 mode 位漂移(
git config core.fileMode false)
2.2 架构调研
产出《Agentos机器人架构调研》(36KB),覆盖:
- 业界 9 项目剖析(rosaOS、ROSA、ros-mcp-server、LiteVLA-Edge、OK-Robot、Octo、RAI、EMOS、Code as Policies)
- MCP 协议与动态能力发现
- 小模型决策引擎设计(Qwen2.5-1.5B/3B + Code as Policies)
- 任务编排状态机(DAG 流转:DISPATCH→EXECUTE→JUDGE→RETRY)
- 边缘硬件部署方案(昇腾310B / 进迭时空K3)
2.3 总体规划(总览四件套)
| 文档 | 内容 | 用途 |
|---|---|---|
| 01-项目大纲 | 项目简介、职责边界、六层架构、技术栈、硬件路线 | 给不了解项目的人的入口 |
| 02-分阶段任务待办 | Phase0~Phase5 极细粒度可勾选待办 | 给要动手的人的 checklist |
| 03-项目完整规划 | 各阶段具体实现方式 + 可选方案利弊 | 给要做技术决策的人 |
| 04-Agent执行约束 | 契约铁律、命名风格、provider 可插拔、安全闸门 | 给写代码的 agent 的紧箍咒 |
2.4 开发方案(已通过审核)
- 方案01:整体计划与开发大纲(ASR 选型、视觉判定分层、首发任务为关灯)
- 方案02:编排核心增强(S2 意图识别 + S3 反馈闭环 + S4 失败重试状态机)
- 审核结论:PASS(可进入 EXECUTE)
- 吸收审核02全部意见(Judge 契约补 evidence、职责切分钉死、MockJudge 不硬编码等)
2.5 边界澄清
- 明确两个隔离的下游黑盒:机械臂(同学A)+ 底盘移动(同学B)
- 路线规划是自有模块(route_planner),夹在 orchestrator 与底盘之间
- 复合任务中 orchestrator 交替调度 VLA 和底盘
- 四份总览文档全部贯通新边界
三、关键决策与取舍
| 决策 | 选择 | 排除 | 理由 |
|---|---|---|---|
| 架构定位 | 多端到端技能 + AgentOS 上层编排 | 单体端到端 | 各技能可独立开发,AgentOS 只做壳 |
| ASR 方案 | 复用 SenseVoice-Small | 自研语音识别 | 254MB、20x 实时、CER~8%,成熟领域不造轮子 |
| 视觉判定 | 本地 YOLO 为主,云端 VLM 为辅 | 全云端 | 快+断网可用,语义判定才上云 |
| 首发任务 | 关灯 | 捡垃圾丢垃圾桶 | 单步定点、反馈直观、最小闭环验证 |
| 编排状态机 | 硬边界 DAG 状态机 | 纯 ReAct 自由发挥 | OK-Robot 经验:刚性状态机大幅提升物理环境成功率 |
| 边缘硬件 | 310B 先演示 → K3 后落地 | 锁定单一平台 | 310B 4GB 内存先跑通,K3 8GB 60TOPS 后上量 |
四、遗留问题与待确认项
需与队友/带教对齐
| # | 问题 | 需要谁 |
|---|---|---|
| 1 | 上游给的是音频流还是音频文件?采样率/格式? | 录音端同学 |
| 2 | 判定图像从哪来?(板载相机/仿真渲染/VLA 回传) | VLA 同学 |
| 3 | 真实 VLA 关灯策略何时给?仿真器是哪套? | VLA 同学 |
| 4 | 命令颗粒度选 A(语义目标)/B(waypoints)/C(离散指令)? | 底盘同学 B |
| 5 | 移动执行结果字段、坐标系/地图来源 | 底盘同学 B |
| 6 | 复合任务分解由谁做? | 底盘同学 B + 带教 |
可推后(不阻塞当前实现)
- 310B 推理后端选型(MindIE vs llama.cpp CPU)
- Code-as-Policies 路径 A/B
- MCP 迁移时机
- 断网降级细化策略
五、下周计划
- 进入 EXECUTE 阶段:按方案02执行 S2→S3→S4 编码
- S2 意图识别增强:文本归一化 + 扩充同义词 + LLM 分类兜底插槽
- S3 反馈闭环骨架:新增
orchestrator.py,MockJudge 实现 - S4 失败重试状态机:DISPATCH→EXECUTE→JUDGE→RETRY/REPORT
- 每步跑
smoke_test.sh回归验证 - 收尾补双轨记录 + 结构化任务清单,交审核03
- (可选)开始方案03 准备:S5 ASR + S6 视觉判定
六、产出文件清单
| 文件 | 位置 | 大小 |
|---|---|---|
| AgentOS任务约束手册 | D:\THU\BeiJing\嘲风\ | ~10KB |
| 任务日志 | D:\THU\BeiJing\嘲风\ | ~14KB |
| 任务详情 | D:\THU\BeiJing\嘲风\ | ~30KB |
| Agentos机器人架构调研 | D:\THU\BeiJing\嘲风\ | ~36KB |
| 开发方案 01/02 | D:\THU\BeiJing\嘲风\开发方案\ | ~11KB + ~15KB |
| 审核结果 01/02 | D:\THU\BeiJing\嘲风\审核结果\ | - |
| 总览四件套 | D:\THU\BeiJing\嘲风\总览\ | ~51KB |
| 本地优先架构讨论 | D:\THU\BeiJing\嘲风\本地优先架构讨论\ | ~60KB |
第 2 周(2026-07-14 ~ 2026-07-18)
宋红 · AgentOS 编排层 / SimCar 端侧探索 阶段声明:从 AgentOS 编排收口进入端侧 SimCar 复合任务 MVP
一、本周工作总览
| 日期 | 主题 | 结果 |
|---|---|---|
| 07-14 | SenseVoice 真实语音入口与会话/磁盘真相核查 | 已完成并归档 |
| 07-16 | 框架复用评估、项目设计和职责边界定稿 | 已完成并归档 |
| 07-17 | AgentOS 基线收口、SimCar Gateway 和无障碍捡球 live 验收 | 已完成 |
| 07-17 | 端侧 Qwen Planner、运动技能、已知几何绕障和复合捡球 MVP | 已实现并通过自动化测试 |
| 07-18 | WSLg 音频穿透、Ollama 模型和实时语音前置条件检查 | 前置条件已确认,实时流尚未完成 |
二、关键成果
2.1 AgentOS 主链收口
- 完成集成分支
integration/agentos-20260717; - 建立独立 SimCar worktree 和
feat/simcar-agent-loop分支; - 保持
route_user_text -> (intent, ToolCall)契约不变; - 保持
vla_service/**和模拟器不变; - 全量测试基线和 SimCar 增量测试均可重复运行。
2.2 SimCar 真值捡球闭环
完成并在线验证:
中文文本
→ Agent API
→ SimCar Gateway
→ 分段前进
→ grab
→ hasBall + armState Judge
→ complete
同时验证了否定指令不下发任何车辆动作。当前能力限定为准备好的无障碍场景和模拟器真值状态,不是视觉 VLA。
2.3 端侧高层 Planner 与已知几何绕障
新增:
- 白名单 JSON
TaskPlan; - Ollama/Qwen Planner 接入点;
- 前进、后退、左右转、停车技能;
- 车辆足迹膨胀和左右绕行几何规划;
- 路径点到 5 cm 控制片段的编译;
- “绕过已知障碍物后捡球”复合执行器;
- 运动任务和捡球任务分别判定终态;
- 未知目标、5 cm 近障碍、碰撞、断连、超时安全失败。
2.4 测试证据
清除 __pycache__ 后的权威结果:
277 collected
267 passed
10 skipped
0 failed
1 existing Starlette/httpx deprecation warning
新增测试覆盖 Planner JSON 校验、技能白名单、运动参数上限、几何路径安全距离、未知目标零运动、复合任务和 Gateway 契约。
三、技术判断
3.1 大模型的职责
端侧大模型只负责:
- 识别用户意图;
- 把抽象指令拆成高层技能;
- 选择目标、方向和任务顺序;
- 在需要时提出澄清。
确定性模块负责:
- 距离、角度和速度上限;
- 障碍物膨胀和路径计算;
- 分段运动;
- 实时状态校验;
- 碰撞、断连、超时和急停。
不能让 1.5B 模型直接输出连续底盘控制量并盲发。
3.2 WSLg 音频穿透
已确认:
PULSE_SERVER=unix:/mnt/wslg/PulseServer;/mnt/wslg/PulseAudioRDPSource存在;- 这说明 Windows 音频输入可以通过 WSLg 的 PulseAudio/RDP source 暴露给 WSL。
尚未完成:
- Ubuntu 内安装
pactl/parec或等效采集工具; - 16 kHz 单声道持续录音验证;
- VAD、音频分片、partial transcript、打断和急停。
3.3 Qwen 1.5B
- 模型文件已经存在于
/root/.ollama/models; - Ollama client 可用,daemon 需要显式启动;
- 需要用基础动作、规则图形和复合障碍任务做计划成功率测试;
- 如果 1.5B 对“这个障碍物”“走个正方形”等抽象指令不稳定,应优先增加
trace_shape等高层技能和澄清机制,再比较 3B/7B 模型。
四、老板演示口径
当前可以说:
AgentOS 已经能把自然语言转换成受约束的高层任务计划,并在已知几何的 SimCar 场景中分段执行、实时检查状态和安全停车。
当前不能说:
已经通过摄像头识别障碍物,具备 GPT-5.6 级任意抽象指令理解,或已经完成未知环境自主导航。
五、下周计划
- 接通 WSLg 实时麦克风采集和音频流入口;
- 启动 Ollama,建立 Qwen 1.5B 计划成功率/延迟测试集;
- 新增 L1 基础运动和 L2
trace_shape技能; - 在已知坐标场景完成绕障 live 验收;
- 增加返回起点、窄通道和 S/8 字路径的纯几何测试;
- 定义视觉/模拟器对象接口,为 L3/L4 真感知闭环接入留出边界;
- 根据实测结果决定继续 1.5B、切换 3B/7B,还是增加专用结构化 Planner。
六、相关归档
- 本周详细日志:
工作日志/; - 总体设计和约束:
总览/; - SimCar 代码、契约、演示和交接:
SimCar/; - 上周启动记录:
周报/第1周-2026-07-07~2026-07-09.md。
第 3 周(2026-07-20 ~ 2026-07-24)
宋红 · AgentOS 编排层 / SimCar 端侧探索 阶段声明:端侧 SimCar 从单句指令推进到多轮对话上下文,补齐规划基准与实时语音闭环,并按老板要求启动 Ascend 310B 端侧 SenseVoice 部署
一、本周目标
承接上周端侧 SimCar 复合任务 MVP,把“单句指令能跑”推进到“多轮场景能接、计划质量可量化、离线也能演示、语音入口可闭环”,并按老板明确要求启动 Ascend 310B / Orange Pi AIpro 20T 上的 SenseVoice 端侧部署。
| 目标 | 对应工作 | 本周结果 |
|---|---|---|
| 收敛 L1 基础动作稳定性 | 确定性快速路径,规避 1.5B 在温度 0 下的漂移与畸形 JSON | ✅ 已完成并通过回归 |
| 打通多轮对话上下文 | 有界会话记忆 + 安全指代补全 + 纯观察话轮 | ✅ 已实现并通过真实链路验证 |
| 建立规划质量与安全门禁 | 36 条中文规划基准,区分 raw / final 与 demo / model 门禁 | ✅ 已建立基准并给出门禁结论 |
| 补齐离线可演示能力 | SIMCAR_REHEARSAL=1 端侧预演模式 | ✅ 已落地并通过契约测试 |
| 接通实时语音入口 | WSLg 实时麦克风采集与虚拟麦克风回放闭环 | ✅ 本机链路已跑通并留证据 |
| 启动 310B 端侧部署 | Orange Pi AIpro 20T / Ascend 310B1 上的 SenseVoice 迁移 | 🔄 板端已连通并盘点,ONNX 已导出;OM 转换阻塞在工具链算子包,持续推进中 |
二、关键成果
2.1 L1 确定性快速路径
上一周的整链验证暴露了一个真实问题:同一句“最大速度前进两秒”在 Qwen2.5-1.5B 温度为 0 时仍会漂移,一次输出正确移动,一次错误输出正方形计划。处理方式不是简单加重试,而是新增高置信 L1 快速路径:
- 方向和米/厘米/秒/角度均明确的基础动作,在调用 LLM 之前就确定性解析;
前进2米、最大速度前进2秒、左转90度、加速/减速不再依赖 LLM 服务是否可用;- 否定句、疑问句和包含“然后/循环/障碍/图形/捡球”等复合语义的句子不进入快速路径;
- L2-L4 抽象任务仍由本地 Qwen 做高层语义选择,再由白名单模板和 Gateway 校验收敛。
修正后,五条合成中文语音的“波形 → SenseVoice → 路由 → 结构化计划”结果为 5/5。
2.2 有界会话上下文与多轮连续避障
此前 UserRequest.session_id 只在响应中原样回传,没有参与路由或规划,第一轮场景陈述和第二轮动作指令彼此独立,“绕过去”缺少可靠的会话目标。本周新增 agent_api.dialogue_context.DialogueContextStore:
- 按
session_id隔离,只保存规范化障碍物目标,不保存音频和完整历史; - 10 分钟不活跃 TTL,最多 128 个会话,超限淘汰最旧状态;
- 超长
session_id使用 SHA-256 生成有界键,进程重启即清空,不伪装成持久地图或世界模型。
在此之上完成三件事:
- 安全指代补全:只补全“绕过去/绕过它/绕开它/避开它”这类明确绕障表达,不补全“把它捡起来”等可能指向球、瓶子或其他物体的歧义操作;路由使用补全后的
resolved_text,执行层仍收到用户原话,两者同时保留在ToolCall.arguments便于回放审计。 - 纯观察话轮:对“前面有个可乐瓶”这类只陈述场景、不含动作或问题的话轮,只记录场景事实,不调用 LLM、不调用 VLA/Gateway,返回
attempts=0并确定性回复“已记录前方的可乐瓶,本轮不执行动作”。 - 绕障前进收敛模板:将明确的“绕障 + 前进距离”收敛为
navigate_forward(distance_cm, side),用户明确左右时以原话为准,模型 JSON 合法时保留模型选择,畸形时用auto或用户侧向兜底,左右冲突/缺距离/带其他任务时不启用模板、继续安全拒绝。
真实 Agent API + Qwen2.5-1.5B + SimCar Gateway dry_run 两轮结果:
第一轮:
intent=llm.general_qa
provider=dialogue_context
attempts=0
answer=已记录前方的可乐瓶,本轮不执行动作。
第二轮:
resolved_text=从左边绕过可乐瓶,然后前进两米
intent=robot.execute_plan
plan=navigate_forward(distance_cm=200, side=left)
final_state=complete
边界判断(诚实口径):多轮对话只解决“同一会话内的绕障指代补全”,刻意不做跨会话共享、跨进程持久、歧义操作补全、把疑问句当场景事实。这样既能支撑连续话术演示,又不会因为过度记忆产生“我会去拿那个瓶子”这类口头承诺与实际行为不一致的风险。
2.3 Qwen2.5-1.5B 规划基准与安全预检门禁
为避免把模板兜底后的效果误报成小模型本身能力,新增 36 条中文规划基准,覆盖 L1 基础动作、L2 几何轨迹、L3 环境交互、L4 组合任务和 8 条安全样例,并分别统计模型原始 JSON 与端侧最终收敛结果:
raw: 18/36 = 50.0%
final: 36/36 = 100%
raw safety: 2/8 = 25.0%
final safety: 8/8 = 100%
guardrail rescues: 18
unsafe raw actions: 6
unsafe final actions: 0
raw model p95: 3.99s
final pipeline p95: 2.04s
warmup: 8.27s
门禁结论为 demo_gate_pass=true、model_gate_pass=false:当前 1.5B 只能在确定性数量落地、白名单模板和安全拒绝共同约束下支撑既定 Demo,不能表述为模型本身达到 GPT 级效果。这条结论是本周最重要的诚实口径。
统计口径判断:
- 把模型原始 JSON 与端侧收敛结果分开统计,是为了不把护栏救回来的 18 次误报成模型能力;
- 模型时延和端侧最终链路时延也分开报,避免把未调用模型的快速路径算进模型性能;
demo_gate_pass关心“既定 Demo 能否稳定跑通”,model_gate_pass关心“模型本身是否达标”;- 当前是前者通过、后者未通过,这决定了对外口径只能讲受约束的 Demo,不能讲模型效果;
- 这套统计口径也是后续对比 3B/7B 的基线。
2.4 端侧离线 rehearsal 模式
现有 dry_run 仍需读取真实 SimCar 状态,模拟器页面或 clientId 不可用时无法独立演示。新增显式 SIMCAR_REHEARSAL=1 模式:Gateway 使用固定 rehearsal fixture,只允许 dry_run=true,任何非预演请求直接返回 409,客户端控制方法也会抛错、不建立远端 SimCar 控制请求。
已在真实本地 Qwen2.5-1.5B、Agent API、Gateway 和 Judge 服务链验证:一米前进、左转 90 度、一米正方形、十次双转向循环、单障碍绕行前进两米,均生成完整有界命令且 final_state=complete,Judge 明确输出“SimCar dry-run 计划已生成,未执行动作”。
2.5 WSLg 实时麦克风与虚拟麦克风回放闭环
- 本机音频设备检查确认存在
RDPSource,parec --device=RDPSource --format=s16le --rate=16000 --channels=1连续采集 3 秒得到 71660 字节 PCM,证明 WSLg 音频穿透和 16kHz 单声道参数可用; - 新增持续采集、能量 VAD、预卷、静音结束、最长话轮限制和 WAV 生成,ASR 与普通动作执行分线程,停车类话术走独立高优先级 Agent 请求可抢占正在进行的普通动作;
- 为避免等待真人现场输入,临时创建 PulseAudio
SimCarMicnull sink 回放中文导航 WAV,Demo 脚本支持--source透传任意 source,真实输出:
[VAD] 话轮 1 已结束,正在识别
[ASR] 前进2米。
[执行] [SIMCAR] 复合任务预演完成
plan: navigate_forward(distance_cm=200, side=auto)
需诚实说明:当前是“持续采集 + VAD 整句话轮 + SenseVoice”,不是逐 token 流式 ASR;应用层急停也不替代硬件急停回路;虚拟麦克风回放不等价于真人声学环境。
2.6 测试证据
清理 __pycache__ 后的权威结果:
355 passed
10 skipped
1 个第三方 StarletteDeprecationWarning
新增覆盖包括:L1 确定性快速路径与否定/疑问/畸形输出回归、会话上下文隔离与 TTL、安全指代补全边界、纯观察话轮零动作、36 条规划基准数据集契约、rehearsal fixture 强制单障碍三航点绕行、VAD 预卷与静音切分、噪声不误触发。唯一警告来自 fastapi.testclient 对 Starlette/httpx 兼容层的第三方弃用提示,与本周代码无关。
2.7 Ascend 310B / SenseVoice 端侧部署(老板明确要求)
按老板要求,启动把 repos/voice-robot 的 SenseVoice 语音控制项目迁移到 Orange Pi AIpro 20T(Atlas 200I A2,Ascend 310B1)的工作,本周完成从零到板端连通、模型导出和工具链定位的第一阶段。
板端连通与盘点
- UART 确认为
COM3,115200 8N1可读到orangepiaipro-20t login:; - 电脑与板端均切到
Tsinghua-Dongsheng,电脑172.16.203.184、板端172.16.203.168,ping通(16-41ms),已建立HwHiAiUser@172.16.203.168的 SSH; - 板端:Ubuntu 22.04
aarch64,acl.get_soc_name()返回Ascend310B1,npu-smi25.2.0,NPU 内存 662/11577 MB;根分区 29GiB 已用 26GiB、仅剩约 2.1GiB,不适合在板端存原始模型或完整工具链;CANN 指向/usr/local/Ascend/cann-9.0.1,Python 3.10.12,amct_onnx0.23.2 可用; - 发现板端 ACLLite 应用缺
libacllite_common.so等三个库,现有 ResNet 示例未跑通,后续需补齐或改写为纯 AscendCL 后端。
本机导出环境与 ONNX
- 在 WSL2(Ubuntu 22.04,x86_64)建
/opt/ascend-sensevoice/venv,装齐torch 2.11.0+cpu/funasr 1.3.22/onnx 1.22.0/onnxruntime 1.23.2等 CPU 导出依赖; - 从 ModelScope 拉
iic/SenseVoiceSmall(原始model.pt约 936MB),导出 ONNX 基线图(输入speech/speech_lengths/language/textnorm,输出ctc_logits/encoder_out_lens); - 新导出器产生的 opset 18 图 CPU 推理成功,但 CANN 9.0.1 ATC 转换 segfault;改用传统导出器生成 opset 14 图(约 895MiB),已同步到板端
/tmp/sensevoice_ascend/model.onnx,两端 SHA256 一致。
OM 转换阻塞点定位(诚实口径)
- 官方公开容器只提供
9.0.1-310p-*,没有 310B 容器;该 310P 镜像 ATC 虽接受--soc_version=Ascend310B1,但选核阶段为大量LayerNorm和 FSMNConv2D报EZ3003 No supported Ops kernel and engine,不能产出可交付的 310B1 OM; - 早期 opset14 图曾被 ATC
Killed,排查确认是 Docker/WSL 编译 OOM,已把 WSL 内存扩到约 11GiB、Swap 8GiB,扩容后固定输入speech:1,100,560的图分析不再被杀; - 已确认板端自带的
/usr/local/Ascend/cann-9.0.1/opp含ascend310b的 Conv2D/LayerNorm 内核,因此改为直接在板端发起Ascend310B1、batch=1、T=100、FP16 的 ATC 编译,等待最终产出。
代码侧新增
- 新增
voice_robot/asr/ascend_backend.py:用 PyACL 执行 OM,CPU 侧实现官方 SenseVoice fbank(16kHz、80mel、25/10ms、LFR 7/6、am.mvnCMVN)和 SentencePiece/CTC 解码,新增--backend ascend及 OM/资源参数; - 前端与 FunASR
WavFrontend数值对齐已验证:同一音频 17 帧×560 特征平均绝对误差约1.6e-6(修正 PCM32768缩放后); - 新增
requirements-ascend.txt、scripts/setup_ascend_board.sh、scripts/run_ascend.sh和 README 的 310B 部署说明,原有 FunASR/RKNN 代码未删除。
当前判断:整套项目可部署在板端,阻塞点是模型转换工具包版本/产品包,不是目标板算力。首版坚持 FP16(先跑通再谈 INT8/INT4),不同时叠加工具链和精度两个变量。板端 ACLLite 缺库、根分区紧张、NPU 健康显示 Alarm 三项待后续处理,现阶段不宣称“部署环境完备”。
2.8 老板演示口径
当前可以说:
AgentOS 已经能在多轮对话中记住同一会话的障碍物目标、补全“绕过去”等省略指代,把自然语言转成受约束的高层任务计划,并在模拟器不可用时用
SIMCAR_REHEARSAL=1完成端侧离线演示:自然语言规划、白名单命令编译、单障碍绕行、实时麦克风/虚拟回放语音闭环都可展示。按老板要求的 Ascend 310B 端侧部署已经打通板端连通、模型盘点和 ONNX 导出,并已定位到 OM 转换的真实阻塞点。
当前不能说:
已经通过摄像头识别障碍物、具备任意抽象指令的 GPT 级理解、完成未知环境自主导航、或已在实体小车/目标端侧硬件上跑通运动;310B 上也还没有产出可交付的 OM、跑通板端 SenseVoice 推理。
三、产出
本周形成的可交付物按“端侧能力 / 基准与证据 / 310B 部署 / 文档归档”四类汇总:
端侧能力
├── DialogueContextStore # 有界会话上下文与安全指代补全
├── L1 确定性快速路径 # 基础动作不再依赖 LLM 漂移
├── 绕障前进收敛模板 # navigate_forward(distance_cm, side)
├── SIMCAR_REHEARSAL=1 # 模拟器不可用时的离线预演模式
└── 实时语音闭环 # WSLg 采集 + VAD + SenseVoice + 高优停车
基准与证据
├── 36 条中文规划基准 # L1-L4 + 8 条安全样例
├── raw / final 双口径统计 # 18/36 → 36/36;安全 2/8 → 8/8
├── demo_gate / model_gate # demo 通过,model 未通过
└── 权威回归 # 355 passed / 10 skipped
Ascend 310B 部署
├── 板端连通与盘点记录 # UART / SSH / NPU / CANN / 分区
├── SenseVoiceSmall ONNX # opset14 ≈ 895MiB,板端 SHA256 一致
├── voice_robot/asr/ascend_backend.py
├── requirements-ascend.txt
├── scripts/setup_ascend_board.sh
├── scripts/run_ascend.sh
└── README 310B 部署说明
文档归档
├── 周报/第3周-2026-07-20~2026-07-24.md
├── 工作日志/ # 本周详细实施记录
├── 总览/ # 总体设计与约束
└── SimCar/ # 代码、契约、演示与交接
关键量化结果速览:
| 项 | 结果 |
|---|---|
| 合成语音整链 | 5/5 |
| 规划基准 raw | 18/36 = 50.0% |
| 规划基准 final | 36/36 = 100% |
| 安全 raw / final | 2/8 → 8/8 |
| raw model p95 | 3.99s |
| final pipeline p95 | 2.04s |
| 回归测试 | 355 passed / 10 skipped |
| 310B OM | 尚未产出可交付 OM(阻塞在工具链算子包) |
四、下周计划
核心目标:把多轮绕障从“单障碍会话补全”推进到“可接感知快照的多障碍路线”,并继续打通 310B 端侧 SenseVoice 可运行基线。
- 感知契约对齐:与模拟器同事约定结构化感知快照契约(
scene_observations:source / confidence / observed_at / 坐标 / 半径),把已知场景几何绕障扩展到多障碍全局路线; - 模型对比评估:在同一 36 条基准上评估 3B / 7B 端侧模型,给出与 1.5B 的成功率 / 时延对比,决定是否引入模型级联;
- 轨迹终点精度契约:dry-run 推进预测位姿、在线执行比对实际位姿,让 Judge 拒绝“命令发完但车没走到”的假完成;
- Ascend 310B 部署推进:在板端自带 CANN 9.0.1 OPP 上完成
Ascend310B1/ FP16 / 固定时长的 OM 转换,补齐或改写 ACLLite 依赖,跑通单音频端到端基线,再评估 INT8 校准; - 动态重规划骨架:增加执行期动态感知刷新与局部重规划的骨架设计,为真实感知服务接入留边界。
五、相关归档
- 本周详细日志:
工作日志/; - 总体设计和约束:
总览/; - SimCar 代码、契约、演示和交接:
SimCar/; - 上周记录:
周报/第2周-2026-07-14~2026-07-18.md。
SimCar 端侧闭环 Demo
能力边界
本 Demo 使用 SimCar 公开真值状态完成“分段接近并抓球”,用于验证 AgentOS 的端侧系统集成。它不是视觉识别、VLA、Nav2 或完整自主避障。
当前承诺:
- 准备好的无障碍场景;
- 文本指令触发自动接近和抓取;
- hasBall + armState=holding 状态判定;
- 碰撞、断连、超时立即停止并失败;
- 否定指令不下发动作。
当前不承诺:
- “这个障碍物”的 grounding;
- 绕障规划;
- 把球放入桶;
- 图像 Judge。
启动
-
等待页面显示 Connected,复制 clientId。
-
在 WSL 中运行:
export SIMCAR_CLIENT_ID=car-xxxxxxxxx export SIMCAR_LIVE=1 bash scripts/demo_simcar_link.sh
页面与终端并排展示。输入“帮我把球捡起来”;输入“不要捡球”可演示安全否决。
坐标校准
2026-07-17 实测:初始朝 -Z 时 rotation=π,left 会增加 rotation;比例采用 API 文档并由 5 cm 前进实测确认约为 1 cm = 0.09 仿真单位。Gateway 因此使用 π 朝向偏移,并在观察到动作进度后等待对应速度归零,避免转向惯性带入下一段。
安全设计
- Demo 配置固定 max_retries: 1;
- 每个移动片段不超过 5 cm;
- 每段动作后重新读取状态;
- 碰撞、状态超时和抓取超时都会发送 stop;
- 退出脚本也会尽力发送 stop;
- live e2e 默认跳过,只有显式设置 SIMCAR_E2E_LIVE=1 才启用。
Reset 现状
公开 reset 接口会返回重置后的 JSON,但 2026-07-17 实测浏览器仿真实体仍可能继续上报旧状态。端侧不能把 reset HTTP 响应当作完成证据;现场以刷新模拟器页面并重新读取状态为准。
端侧大模型驱动的 SimCar 复合任务 MVP
能力定位
本模块让端侧 Qwen 负责把自然语言拆成受约束的高层技能计划,再由确定性几何规划器和反馈控制器执行。大模型不直接输出电机命令,也不能编造障碍物坐标。
当前可验证能力:
- 文本或 SenseVoice 音频入口;
- 端侧 Ollama/Qwen 生成白名单 JSON 任务计划;
- 前进、后退、左右转和停车,带距离、角度和分段上限;
- 根据配置中的已知障碍物坐标和尺寸生成左右绕行路径;
- “绕过已知障碍物后捡球”复合执行;
- 每段运动后读取 SimCar 状态;
- 碰撞、断连、超时、未知目标、距离过近和非法计划立即停车并失败;
- SimStateJudge 按运动或捡球任务分别检查终态。
当前不能宣称:
- 从相机图像识别可乐瓶或任意障碍物;
- 对“这个”做真实视觉 grounding;
- 在未知或动态障碍环境自主导航;
- 大模型直接进行安全的低层连续控制。
模块
SenseVoice / text
→ agent_api.task_planner(端侧 LLM,白名单 JSON)
→ router / orchestrator(否定拦截、单次执行)
→ simcar_gateway_service.skills.task_plan
→ KnownScene(只接受可验证几何)
→ GeometricAvoidancePlanner(车辆足迹膨胀、左右候选)
→ WaypointNavigator / SafeMotionSkill(分段反馈控制)
→ DirectPickBallSkill
→ SimStateJudge
任务计划只允许:
move(direction, distance_cm)
turn(direction, angle_deg)
stop()
navigate_around(target, side, clearance_cm?)
pick_ball()
Gateway 会在执行前再次校验整个计划并解析所有目标,避免执行一半后才发现后续目标未知。
启动
先打开 https://simcar.chenlongrobot.com/,刷新页面,等待 Connected 并复制新的 clientId。准备无动态障碍场景,测量可乐瓶在 SimCar x/z 坐标系中的位置。
cd /root/chaofeng/.claude/worktrees/simcar-agent-loop/agent-llm-vla
export SIMCAR_CLIENT_ID=car-xxxxxxxxx
export SIMCAR_OBSTACLE_X=0
export SIMCAR_OBSTACLE_Z=-5.4
export SIMCAR_LIVE=1
bash scripts/demo_simcar_agent.sh
需要本机 Ollama 已运行并准备 qwen2.5:1.5b。首次语音请求会加载 SenseVoice。
文本示例:
dry 绕过前面的可乐瓶,把球捡起来
绕过前面的可乐瓶,把球捡起来
前进10厘米
向右转30度
停车
音频文件示例:
@audio /root/sv_rec/avoid_and_pick.wav
安全约束
- Demo 固定
max_retries: 1,碰撞后不盲目恢复; - 平移动作每段不超过 5 cm;
- 单次自然语言平移不超过 100 cm,转向不超过 180°;
- 30 cm 正方形车辆按半对角线计算旋转扫掠半径;
- 障碍物坐标缺失或别名无法唯一解析时,不发送运动命令;
- 初始位置位于障碍物膨胀安全区内时,只停车并返回
unsafe_initial_clearance; stop是确定性规则技能,不依赖大模型规划成功;- 退出 Runner 时尽力发送
stop。
感知接入点
未来视觉或模拟器对象接口应把检测结果转换为与 KnownScene 等价的结构,并带来源、时间戳和置信度:
{
"name": "coke_bottle",
"aliases": ["可乐瓶"],
"x": 0.0,
"z": -5.4,
"radius_cm": 3.3,
"source": "rgbd_detector",
"timestamp": "...",
"confidence": 0.93
}
在加入真实感知前,演示必须表述为“已知几何绕障”,不能表述为“视觉识别绕障”。
蒋丰泽
在 rk3588 开发板上开发轮足机器人,实现平衡控制、机械臂托举等功能。并将 Starry OS 改造成实时操作系统,移植到机器人上。
核心任务
在此项目中我负责机器人的结构选择,硬件配置,平衡控制。
选型
针对轮足机器人在市面上进行了大量调研,选型,发现在售的成熟产品不多。寻找了开源项目,成熟的路面级也很少。
努力寻找轮足机器人合适的机械结构以及相应电机,得出合适的架构有两种,一个是四电机方案,一个是六电机方案。
四电机:简单、轻量、高效率。
六电机:增加腿部自由度,提高地形适应能力和运动能力。
最后综合考虑需求暂时确定六电机结构。
准备
为轮足机器人所需要的算法和模型进行环境配置和学习,准备为轮足机器人的平衡控制进行算法控制和模型训练。配置了isaac gym环境,并学习与之相关的使用教程,和强化学习的知识。为后面机器人可能需要的建模做足了充分准备。
下周工作
等下周有了原型机器,对其进行研究算法控制,和模型训练。为其接入大脑,移植所需要的驱动等。
本周工作
1.机器人腿部与外壳需要3d打印或其他,学习了建模软件以满足需要
2.继续在网络上寻找开源项目,寻找到了相关的项目,项目图片存放在了project文件夹的open文件夹中。源代码及制图文件因为过大,放在了本地。
3.学习了机器人可能要用到的平衡算法:PID,LQR,学习总结和相关概念放在了project文件夹的balance文件夹
下周工作
争取在下周将机器3d打印模型打印出来并加上硬件设备
寻找合适平衡算法以适配原型机
第三周
本周目标
将开源项目1复现
成果
阅读了大部分程序源码,对机器人的控制系统有了全面的认知。采购了机器人硬件,大部分已经到达。对电机进行了调试,使用正常。机器人原本电池因网购不能运往北京,暂时改为其他现有插线电源供电。3d打印外壳因为3d打印机最近不空闲,暂时不能打出完整外壳。
下周目标
将3d文件打印好后,将硬件组装好,并将源码进行需要的改动后移植进入芯片,进行调试。
第四周
本周工作
完成了小车组装,并开始进行调试
在组装过程中,打印件有些不适合小车,于是我们自己重新设计了一些打印件来适配小车。
3d视图软件中有些小车配件没有在图里,使用时才发现问题,重新加购了rs485转ttl模块。
但上位机通过转接模块连接不到电机,准备采取其他办法
下周目标
使小车站起来,进行平衡控制
对每个模块和esp32进行链接适配
对开源代码进行参数适配,使小车保持平衡站起来
工作内容
平衡控制 (Balance)
LQR 控制
PID 控制
Open 项目
项目截图
叶志阳
针对 Orange Pi AIpro20T 平台,实现 SmolVLA 论文当中的异步推理,并利用昇腾 NPU 完成 SmolVLA 的推理加速、优化和部署。同时对 RK3588 端侧部署进行可行性验证,用于后续真实硬件输入、Agent 和语音交互接入。
第一周(2026-07-06 ~ 2026-07-10)
本周目标
围绕 Orange Pi AIpro20T 平台,完成 SmolVLA 异步推理链路的前期调研、模型拆解、板端部署验证和 NPU 加速瓶颈分析,为后续实现稳定的异步推理服务和算子级优化打基础。
主要工作
- 梳理 SmolVLA 推理流程,明确视觉输入、语言输入、状态输入和动作输出之间的数据依赖关系。
- 分析主机端与板端的运行环境,确认 Orange Pi AIpro20T 上昇腾 CANN、ACL Runtime、自定义算子和 benchmark 的基本使用方式。
- 拆分 SmolVLA 推理链路中的关键子图,围绕视觉编码、语言/动作条件、denoise 循环和 action head 进行导出与板端验证。
- 搭建 ACL/ACLLN 侧的输入构造、模型运行、结果对齐和耗时统计脚本,用于比较 CPU/PyTorch 参考结果与 NPU 推理结果。
- 针对 attention 计算路径进行性能分析,对比普通 Attention 拆算子方案与 FlashAttention 思路在 310B1 上的可行性。
- 使用 Ascend C 尝试实现 FA1 attention kernel,验证 QK、online softmax、P@V 等路径的正确性、数值稳定性和板端性能。
- 对 P@V 的 vector 累加、Cube MatMul、GM workspace、UB/TSCM 数据布局等方案进行实验,定位当前自定义 FA1 kernel 慢于 BatchMatMulV2 + SoftmaxV2 + BatchMatMulV2 的原因。
- 形成当前优化判断:简单局部 vector 化收益有限,后续需要从 tile 调度、K/V 复用、更大 fused tile 或更合适的 MatMul 调用模型上继续优化。
当前结论
SmolVLA 在 Orange Pi AIpro20T 上可以通过拆分子图和 ACL Runtime 逐步推进部署,但 attention 路径是主要性能瓶颈之一。当前自定义 FlashAttention 原型已经完成正确性验证,但要超过平台内置 BatchMatMul/Softmax 拆算子方案,需要进一步减少小 MatMul 调用次数,并提高 K/V tile 的复用效率。
下周计划
- 继续推进 SmolVLA 异步推理框架,把视觉编码、语言条件和动作生成拆成可流水执行的任务。
- 优化 attention kernel 的 tile 组织方式,重点验证多 Q block 共享 K/V tile 和更大 fused tile 的可行性。
- 完善板端 benchmark,记录端到端延迟、单子图延迟、NPU 利用率和精度误差。
- 将可稳定复现的部署步骤整理成文档,便于后续移植和复测。
第二周(2026-07-13 ~ 2026-07-17)
本周目标
本周围绕 SmolVLA 在端侧的完整推理部署继续推进,重点验证 Ascend 310B 与 RK3588 两条路线的性能、数值对齐和工程可接入性。接口契约本周保持不变,后续再把当前推理服务改造成适配项目统一接口的形式。
主要工作
- 完成 Ascend 310B 侧 full-chain 推理链路的持续测试,覆盖 vision encoder、prefix、denoise、action unnormalize 等关键阶段。
- 对 denoise loop-OM 调度进行验证,尝试使用 s4 + s4 + s2 的分段调度替代原来的 10 次 denoise step + update 循环。
- 增加服务侧 instrumentation 设计,计划统计
load_inputs_ms、tokenize/lang_ms、save_outputs_ms、json_response_ms、request_wall_ms、core_total_ms等分段耗时。 - 分析 310B 上 attention core、Softmax、GELU、LayerNorm、RoPE/RMSNorm 等算子路径,确认哪些可以继续尝试平台内置算子替换,哪些暂时不适合作为主线。
- 对 W8A8、W8A16、W4A16 等量化方向做分组分析,重点区分 activation INT8 误差和 weight-only 量化误差。
- 在 RK3588 上推进 SmolVLA 子图部署,完成 vision、connector、prefix、denoise 等 RKNN 子图的导出、转换和数值验证。
- 定位 RK3588 prefix RKNN 的数值漂移问题,并验证 CPU/ONNXRuntime fallback 与部分 prefix 层 RKNN 混合执行的可行性。
- 梳理后续接入真实硬件图像、状态、Agent 和语音输入时需要的请求结构和常驻推理服务形态。
当前效果
Ascend 310B 侧推理链路已经可以跑通完整 action 输出,当前粗略耗时量级如下:
| 阶段 | 当前耗时 |
|---|---|
| vision encoder 0-12 | 约 205-210 ms |
| prefix | 约 62 ms |
| denoise step path | 约 156 ms |
| 端到端 | 约 450 ms 量级 |
denoise loop-OM 的 s4 + s4 + s2 调度可以让 denoise 阶段稳定减少约 8-9 ms,但 loop OM 常驻后会让 vision 侧变慢约 14-16 ms,抵消 denoise 收益。因此后续需要在常驻进程内做 repeated inference benchmark,避免模型加载、GE 资源状态和 vision 波动干扰结论。
RK3588 侧已经完成多个子图验证:
| 子图 | 结果 |
|---|---|
| vision encoder | 通过 canonical tanh-GELU rewrite 后,monolithic RKNN 与 ONNX 对齐,cos 约 0.999108,单次 latency 约 995.8 ms |
| vision connector | 输出形状 [1,64,960],cos 约 0.999999968,median latency 约 42 ms |
| denoise RKNN | 在输入 ONNX prefix KV 时,action_unnorm_7 cos 约 0.999999744,max_abs 约 0.001160 |
| prefix RKNN | full prefix RKNN 仍不可用,action_unnorm_7 cos 约 0.924520644 |
已排除或暂不作为主线的路径
- Ascend 310B 自定义 FlashAttention 暂不作为主线。当前平台上未找到稳定可用的官方 PFA/IFA 路线,attention core 单层已经是个位数毫秒,继续手写 kernel 的收益风险比不高。
- W8A8 全量 activation 量化暂不作为主线。已有单层结果显示主要误差来自 activation INT8,而不是 weight INT8:layer0 MLP W8A8 cosine mean 约 0.994554,act16+w8 cosine mean 约 0.999334。
- INT4 不适合直接全量铺开。只有在 W4A16 能带来至少 10-15 ms encoder latency 收益,并且 action drift 接近 W8A16 时才值得继续。
- RK3588 full prefix RKNN 暂不能用于端到端主链路。prefix 的 hidden-state fp16 误差会在后续层放大,
optimization_level=0与 level3 表现接近,说明不是单纯全局融合开关导致。 - RK3588 prefix CPU/ONNXRuntime fallback 数值正确,但延迟过高;prefix ORT 约 1000 ms,denoise RKNN x10 约 1841 ms,端到端接近 3 s,不满足实时目标。
下一步计划
- 固定 Ascend benchmark 方法,改为同一常驻进程内 warmup 3 次、repeat 20 次,输出 total、vision、prefix、denoise 的 median 和 p95。
- 优先优化 runtime 层面的内存与输入管理,包括
aclrtMalloc/free池化、静态输入 device 常驻、denoise time embedding 预计算、连续内存 view 替代冗余 D2D copy。 - 对 vision encoder 做小范围受控算子实验,优先验证 GELU/GeluV2 或 NPUFastGelu 替换是否能稳定编译、profile 变快并通过 full-chain action drift。
- 量化继续沿 weight-only / A16W8 方向推进,先做 MLP only、projection only、MLP + projection 的小 A/B,不再盲目扩大 W8A8。
- RK3588 暂定位为功能集成和接口验证平台。后续如要实时化,需要模型结构压缩、蒸馏或减少 prefix/vision 计算量。
- 保持当前接口契约不变,后续新增适配层把 VLA request、图像/state 采集、Agent 文本输入、语音识别输入接入常驻推理 worker。
第三周(2026-07-20 ~ 2026-07-24)
本周目标
本周实际没有继续大规模推进 Ascend 310B 的算子级优化,主要工作转向三件事:
- 复查远端仓库中已经存在但个人周报里没有展开的 Agent/VLA/LLM 接口接入基础,明确后续 SmolVLA 推理服务应如何适配现有契约。
- 围绕 SG2002 上 ACT 推理链路做非 JPU 优化和验证,摸清当前软件侧性能边界,并固定稳定 baseline。
- 调研
llama.cpp与更适合 VLA 推理移植的vla.cpp路线,判断是否可以作为后续 RK3588、Orange Pi 或其他端侧平台的长期部署方向。
接口契约本周仍不修改。后续改造方式应是在现有 /v1/execute 外围新增 provider 或 bridge,把当前 SmolVLA resident worker 适配进去,而不是直接改 common/schemas.py。
远端仓库已有但此前未展开的工作
远端仓库里已经有一套 Agent、VLA、LLM 解耦框架,个人周报之前只简单提到“接口接入”,没有把可复用部分写清楚。本周重新梳理后,后续 SmolVLA 部署可以直接复用以下设计。
三服务拆分
当前架构把系统拆成三个 HTTP 服务:
| 服务 | 职责 | 后续与 SmolVLA 的关系 |
|---|---|---|
| Agent API | 接收用户文本,判断机器人任务或通用问答 | 后续接语音识别结果、Web/Socket 文本输入、任务路由 |
| VLA Service | 暴露机器人技能列表并执行指定技能 | 后续新增 ascend_vla、rknn_vla 或 remote_vla provider |
| LLM Service | 提供通用语言生成能力 | 后续可接 Ollama、llama.cpp server 或云端模型 |
这个拆分对当前部署工作很关键:VLA 侧可以频繁替换 PyTorch、ONNX、OM、RKNN、C++ runtime,而 Agent 侧只依赖统一接口,不需要知道底层推理后端。
当前 VLA 契约
VLA Service 目前已经定义:
GET /v1/skills:返回白名单技能。POST /v1/execute:执行一个 VLA 技能。
请求字段目前包括:
{
"skill_id": "ball_pick_v1",
"user_text": "帮我把球捡起来",
"duration_s": 15,
"dry_run": false,
"metadata": {}
}
这和我们之前单独设计的 VLARequest(prompt, images, state, timestamp, episode_id, reset, seed/noise) 不完全一致。因此下一步不应直接改契约,而应在 VLA provider 内做适配:
skill_id查configs/app.yaml,拿到固定 task prompt 和 policy 配置。user_text只作为上层用户原始输入保留,真正喂给模型的 prompt 优先使用技能固定 prompt。metadata暂时承载图像路径、base64 图像、机器人 state、episode_id、reset、timestamp 等扩展字段。- provider 内部把这些字段转换成 resident worker 需要的输入 bundle。
- 返回时把
action_unnorm_7、分段耗时和后端信息放入metadata或raw_result,保持外层响应结构不变。
已有 provider 与可扩展点
仓库里已经有:
mockprovider:用于不控制真实机械臂的接口联调。lerobot_rolloutprovider:通过lerobot-rollout调真实 SmolVLA/LeRobot。- 文档中预留的
remote_vla、ascend_vlaprovider:适合接板端常驻推理服务。
因此后续最小改造路径是新增 provider,而不是重写 Agent:
Agent /v1/chat
-> VLA Service /v1/execute
-> ascend_vla provider
-> resident SmolVLA worker
-> action_unnorm_7 + latency metadata
与语音和 Agent 的关系
远端文档中已有语音、AgentOS、多轮对话和工具调用相关内容。对本人的 SmolVLA 部署任务来说,需要对齐的是输入输出边界:
- 语音识别模块只需输出文本,进入 Agent 的
/v1/chat。 - Agent 只负责选择技能和生成受约束 tool call,不直接拼模型 tensor。
- VLA provider 负责采集或接收图像/state,并调用真实推理后端。
- 真实执行结果不能只看
ok=true,还需要后续视觉反馈或机器人状态确认。
这说明后续 VLA 侧最重要的是补齐常驻 worker 的服务化接口和耗时 instrumentation,而不是先修改全局 schema。
RK3588 侧进展补充
本周将 RK3588 路线进一步收敛为“功能集成与接口验证平台”,而不是主实时推理平台。已有实验结论如下:
| 模块 | 当前状态 | 结论 |
|---|---|---|
| vision encoder RKNN | canonical tanh-GELU rewrite 后 monolithic RKNN 与 ONNX 对齐,cos 约 0.999108 | 数值问题可修,但 latency 约 995.8 ms |
| connector RKNN | cos 约 0.999999968,median latency 约 42 ms | 可用于 image-to-prefix 闭环 |
| denoise RKNN | 输入 ONNX prefix KV 时 action_unnorm_7 cos 约 0.999999744 | 子图本身可用 |
| prefix RKNN | full prefix RKNN 最终 action cos 约 0.924520644 | hidden fp16 误差会逐层放大,不适合主链路 |
已经排除的路径包括:
- full prefix monolithic RKNN:数值漂移不可接受。
- 仅调整 RKNN
optimization_level:level0 与 level3 表现接近,不能解决 drift。 - 使用 RKNN float32、tfloat32、bfloat16:工具链不支持或转换失败。
- prefix CPU/ONNXRuntime fallback:数值正确但端到端接近 3 s。
- prefix 前 2 层 RKNN + 后 30 层 ORT:数值可接受但没有实际时延收益。
因此 RK3588 后续更适合用于验证:
- 图像输入格式;
- state 输入格式;
- skill/prompt 到 action 输出的接口闭环;
- Agent/语音/前端服务联调;
- 简化模型或蒸馏模型的部署可行性。
SG2002 ACT 非 JPU 优化与验证
本周还围绕 SG2002 上 ACT 推理链路做了非 JPU 方向的优化验证,重点不是更换模型,而是把当前软件侧可达到的性能边界摸清,并形成可长期复测的 baseline。
CVI runtime split/no-TaskPool 接口改造
在 cviruntime 中补充并验证了 no-TaskPool split API:
CVI_NN_ForwardSubmitNoWait
CVI_NN_ForwardWaitNoTaskPool
CVI_RT_RunCmdbufExSubmit
CVI_RT_WaitCmdbuf
同时将修改后的 runtime 持久化到本地工具链目录,并覆盖到板端 /usr/lib 和 /root/sg2002-act/lib,解决了应用侧调用 split API 时的动态链接问题。
异步探针与调度行为验证
新增并测试 cvi_async_probe,用于区分同步推理、异步 submit/wait、producer overlap 的行为。验证结果如下:
- split API 功能正确;
- 输出与同步路径一致;
- submit 确实是非阻塞;
- busy producer 会拖慢总耗时;
- yield/sleep producer 才能体现 overlap。
这说明在 SG2002 + StarryOS 单核环境下,CPU busy 型 producer 会影响 TPU wait、IRQ 或 polling 进展。也就是说,异步 submit 本身可用,但单核系统上的 CPU 抢占会抵消一部分 overlap 收益。
ACT 推理链路 split-async 改造
将高性能 ACT 推理程序改造成同时支持:
--inference-backend sync
--inference-backend split-async
并实现了单线程 overlap eval:当前帧提交 TPU 后,CPU 预处理下一帧,再等待当前帧结果。该路径输出与同步路径完全一致,证明 split-async 实现正确。
不过 20 帧和 100 帧测试都显示当前异步流水没有实际收益:
| 后端 | avg_eval_wall_ms |
|---|---|
| sync | 65.294 ms |
| split-async | 66.585 ms |
当前结论是:在 SG2002 + StarryOS 单核 + 当前 CVI runtime 条件下,异步 overlap 的调度开销和 CPU 抢占成本抵消了可隐藏的预处理时间。因此异步路径保留为实验和诊断工具,不作为默认优化方向。
turbojpeg + RVV 同步 baseline
构建并部署了 act_cvi_infer_turbo_split,支持:
--jpeg-backend turbojpeg
--preprocess-backend rvv
--inference-backend sync
当前最优非 JPU baseline 为:
| 阶段 | 耗时 |
|---|---|
| JPEG decode | 约 9.5 ms |
| RVV resize | 约 3.3 ms |
| fill | 约 0.3 ms |
| TPU | 约 51.6 ms |
| postprocess | 约 0.2 ms |
| total | 约 65 ms/frame |
其中 TPU 推理约占总耗时的 79%,说明在不动模型、不降低精度、不接 JPU 的前提下,非模型侧继续优化空间已经较小。
依赖与部署问题
补齐并验证了板端动态库依赖:
libcviruntime.so
libturbojpeg.so.0
libcvikernel.so
libcvimath.so
确认二进制 RPATH 为:
$ORIGIN/../lib
并修复了 libturbojpeg.so.0 缺失导致的运行失败问题。
当前结论
SG2002 上当前建议默认主线固定为:
turbojpeg + RVV + sync
异步 split 路径保留为实验分支,用于后续诊断 CVI runtime、TPU wait、producer/consumer overlap 行为。后续非 JPU 方向预计只剩小幅收益,包括减少日志和 I/O 干扰、小幅优化 RVV resize、减少输入填充开销,以及利用 ACT action chunk 降低推理频率。若要继续拿到明显额外收益,JPU 仍是后续最值得验证的硬件输入链路优化方向。
SenseVoice 310B1 基准测试补充
虽然本周没有继续深入 SmolVLA 在 Ascend 310B1 上的算子优化,但远端语音链路已经有可用于后续 Agent/VLA 接入的实测基线:SenseVoiceSmall FP16 OM 已经能在 Ascend 310B1 上通过 PyACL acl.mdl.execute 成功执行,并完成了基础内存和时延测试。
测试条件
| 项目 | 配置 |
|---|---|
| 模型 | SenseVoiceSmall FP16 OM |
| 固定输入 | 1 x 100 x 560,约支持 6 秒语音 |
| 测试音频 | 官方 5.616 秒中文样例 |
| 推理接口 | PyACL acl.mdl.execute |
| 预热 | 5 次 |
| 正式测量 | 30 次 |
| OM 文件大小 | 466.54 MiB |
时延结果
| 指标 | 结果 |
|---|---|
| 未预热首次推理 | 约 39.36 ms |
| 预热后平均时延 | 约 33.07 ms |
| P50 | 约 33.09 ms |
| P90 | 约 33.13 ms |
| 最低时延 | 约 32.89 ms |
| 最高时延 | 约 33.21 ms |
| 模型加载时间 | 约 3.45-3.51 s |
对于 5.616 秒中文音频,纯 NPU 神经网络推理约 33 ms,相当于约 170 倍实时速度。这说明语音识别模型本体在 310B1 上不是主要瓶颈,后续真正需要关注的是端到端链路。
NPU 内存结果
| 指标 | 结果 |
|---|---|
| NPU 内存增量 | 约 920-921 MB |
| 加载后 NPU 内存 | 约 2687 MB |
| 预热后 NPU 内存 | 约 2687 MB |
| 退出后 NPU 内存 | 约 1731-1732 MB |
预热后没有发现额外 NPU 内存增长,因此当前可以把 SenseVoiceSmall FP16 OM 的实际运行内存按约 0.9 GB 估算,占 310B1 约 11.6 GB NPU 内存的 7.95%。从内存角度看,不需要为了部署 SenseVoiceSmall 立即做 INT8 量化。
端到端影响
上述 33 ms 只包含 OM 推理,不包含以下开销:
- 音频录制和 VAD;
- fbank/LFR/CMVN 特征提取;
- H2D/D2H 数据拷贝;
- CTC 和 SentencePiece 解码;
- 中文指令理解;
- HTTP 控车或 VLA 服务调用。
因此完整语音到动作链路的端到端延迟一定高于 33 ms。当前估计语音前后处理和解码会额外增加几十毫秒,后续需要在完整 Ascend 后端中实测,不能直接用纯 OM 推理时延代表最终交互时延。
风险说明
板端 NPU Health 仍显示 Alarm,系统仍存在 17 个 D 状态驱动线程和 LPM 异常。虽然 FP16 OM 当前可以正常加载、推理,并且退出后 NPU 内存能基本释放,但生产部署前仍应优先解决驱动健康告警,避免长时间运行时出现资源泄漏、推理阻塞或设备不可恢复。
当前结论是:SenseVoiceSmall FP16 OM 可以在这块 310B1 上运行,纯模型推理约 33 ms,实际占用约 920 MB NPU 内存;它适合作为后续语音输入入口接入 Agent/VLA 链路,暂时没有必要为了内存占用立即投入 INT8 量化。
llama.cpp 调研
本地 Embodied.cpp/third_party/llama.cpp 已经存在,并且处于有本地修改的状态,说明此前已经开始围绕 GGUF/ggml runtime 做迁移准备。llama.cpp 的主要价值是:
- C/C++ 推理栈成熟,适合减少 Python、PyTorch、Transformers 等运行时依赖。
- GGUF 模型格式和 ggml kernel 体系适合做权重量化、CPU fallback 和跨平台部署。
- 可以作为 LLM Service 的本地 provider,替换 Ollama 或云端 LLM。
- 其多模态相关代码可以为 vision encoder、token/image adapter 的 C++ 化提供参考。
但 llama.cpp 本身不是完整 VLA runtime,直接迁移 SmolVLA 有几个风险:
| 风险 | 影响 |
|---|---|
| 缺少 VLA action head 原生流程 | SmolVLA 的 prefix cache、cross-attention、flow/diffusion denoise loop 仍需手工实现 |
| 多模态路径主要面向 VLM,不等同于机器人 action 输出 | 不能只把语言模型跑起来就认为 VLA 已迁移 |
| Ascend 310B / RK3588 NPU 后端不是 llama.cpp 主线 | 很可能只能先跑 CPU,端侧 latency 未必优于 ONNX/RKNN/OM |
| 模型转换工作量大 | 需要确认权重命名、tensor layout、tokenizer、image preprocessing、action normalization 全部一致 |
| 数值验收复杂 | 必须逐层或逐阶段对齐 PyTorch/ONNX reference,不能只看最终动作能否输出 |
因此 llama.cpp 更适合作为底层 runtime 参考和本地 LLM provider,不建议直接作为 SmolVLA 主迁移入口。
Orange Pi / Ascend 上的 llama.cpp 相关线索
本周额外阅读了几条与 Orange Pi AIpro / Ascend NPU 上部署 Llama/ggml 相关的公开资料。只保留能从仓库或官方文档中确认的信息,结论是:这条路线可以作为 LLM provider 或 C++ runtime 参考,但不能直接证明 SmolVLA 可以低成本迁移。
| 来源 | 可确认信息 | 对当前项目的意义 |
|---|---|---|
lenLRX/llama_orangepi | 该仓库基于 Meta Llama 代码做 OrangePi 20T 推理实验;README 明确写到直接推理会 OOM,需要额外开启约 24G swap;还提到 cann_kb_init 需要用 cann_patch 替换;7B 测试结论是“仅仅是能跑” | 说明早期 torch_npu/PyTorch 路线依赖重、内存压力大,不适合作为低延迟常驻服务主线 |
Burtinsaw/GGML-CANN | 该仓库目标是给 ggml 添加 CANN backend,README 直接面向 OrangePi AI Pro 20T / Ascend 310B1,并给出动态 shape MatMul、CANN context、kernel bin、kernel meta、静态 buffer、backend 注册等实现说明;同时作者说明测试板 NPU health 处于 alarm,实际端到端示例只验证了 CPU fallback | 这是比纯 PyTorch 路线更接近我们需求的 C++/ggml/CANN 参考,但当前还不能当作“310B1 NPU 已稳定跑通 llama.cpp”的证据 |
| llama.cpp CANN backend 文档 | 官方 llama.cpp 已有 CANN backend,使用 AscendC/ACLNN;支持 Linux,文档列出 910B、310P 支持情况,模型格式支持 FP16/Q4_0/Q8_0;同时有 CANN memory pool、ACL graph、operator fusion、prefill graph 等环境变量 | 对我们有参考价值,尤其是常驻内存池、ACL graph、算子融合开关;但文档中没有把 Orange Pi AIpro 20T / Ascend 310B1 列为已验证目标,因此不能直接假设可稳定复用 |
这里最重要的判断是:llama_orangepi 更像是“PyTorch/torch_npu 能跑通 Llama2 7B”的验证,不是轻量 C++ runtime;GGML-CANN 更接近我们想要的 C++/ggml/CANN 改造方向,但它自己也明确受 NPU health alarm 影响,尚未给出可靠的 310B1 NPU 端到端 LLM benchmark;官方 llama.cpp CANN backend 更工程化,但公开验证目标主要是 910B/310P。因此如果后续要把本地 LLM 放到 Orange Pi 上,推荐顺序是:
- 先在 x86 或板端 CPU 上跑通
llama.cppGGUF 小模型,接入 LLM Service。 - 单独复现
GGML-CANN的最小 ggml backend 测试,确认本机 310B1 在 NPU health 正常时能否进入 CANN backend,而不是落到 CPU fallback。 - 再尝试官方
llama.cpp的GGML_CANN=on路线,记录能否编译、加载、生成、释放内存。 - 对比 CPU、CANN backend、Ollama/MindIE 的首 token、decode token/s、NPU 内存和长期稳定性。
- 只有在 LLM provider 稳定后,再考虑把相关 runtime 经验迁移到 VLA,而不是把 SmolVLA 直接塞进 Llama 官方 PyTorch 代码路径。
vla.cpp 调研
相比 llama.cpp,vla.cpp 与当前任务更贴近。它是基于 llama.cpp/ggml 的 VLA 推理 runtime,目标就是把 VLA 从 Python/PyTorch 栈迁到 C++ 推理栈中。公开 README 中已经说明支持 SmolVLA、π0、BitVLA、Evo-1、GR00T N1.x 等 VLA,并以单个 GGUF bundle 方式部署;推理时不依赖 Python 或 PyTorch。
它对当前项目有几个直接参考价值:
- 模型组织方式:把 vision-language prefix、cross-attention KV cache、action head 和 denoise/flow step 放进统一 runtime,而不是把每个子图拆成多个 ONNX/OM/RKNN 文件。
- 服务形态:提供常驻 server,一次加载模型,多次接收请求,这与我们在 310B 上想做的 resident worker 一致。
- 输入协议:CLI/server 接收图像、tokenized instruction、state,然后输出 action chunk;这和我们计划的 VLARequest 很接近。
- GGUF 打包:SmolVLA 可以转换成自包含 GGUF,便于部署、版本管理和模型文件分发。
- 量化路线:支持对 LM backbone weight 做 GGUF 量化,如 Q8_0、Q4_0;vision tower、norm、action expert 可以选择保留浮点,符合我们此前“activation INT8 误差大,优先 weight-only”的判断。
- benchmark 方式:常驻 server + client 重复请求的模式可以借鉴,用来替代当前容易受加载和资源状态影响的单次进程 benchmark。
公开 benchmark 显示,vla.cpp 的 SmolVLA 在不同平台上已经做过端侧测试,例如 RTX 3090、Jetson AGX Orin、Jetson Orin Nano、Apple M4。这个对 RK3588/Orange Pi 没有直接保证,但说明它至少比单纯 llama.cpp 更接近我们的部署问题。
vla.cpp 的主要风险
| 风险 | 影响 | 应对计划 |
|---|---|---|
| 仓库较新,接口和格式可能变化 | 直接接主线可能频繁返工 | 先 pin commit,做独立实验目录,不污染当前服务契约 |
| 没有 Ascend 310B / RKNN 后端 | 可能只能跑 CPU,无法直接利用 NPU | 先在 x86/RK3588 CPU 跑正确性和接口,再评估 ggml 后端扩展 |
| SmolVLA checkpoint 兼容性未知 | 我们训练/导出的 checkpoint 可能不能直接转换 | 先用公开 smolvla-libero GGUF smoke test,再试自有 checkpoint 转换 |
| tokenizer 和 prompt 输入形式不同 | Agent 输出文本到 token ids 之间需要桥接 | provider 内固定 tokenizer,不把 token ids 暴露到 Agent 契约 |
| action normalization/statistics 必须一致 | 输出 action 可能数值对齐但物理尺度错误 | 把 dataset statistics、action_mean/std 纳入 drift 测试 |
| 端侧 CPU latency 仍可能偏高 | RK3588/310B CPU 不能满足实时 | 只把它作为 C++ 化和模型压缩方向,不替代当前 310B OM 主线 |
下一步计划
- 新增
ascend_vla或remote_vlaprovider 草案,但不修改VLAExecuteRequest/VLAExecuteResponse契约。 - 将 SmolVLA resident worker 包成服务模式,接收 prompt、image、state,返回
action_unnorm_7与分段耗时。 - 从远端现有
/v1/execute的metadata字段接入图像/state,先完成 mock 请求到真实 worker 的闭环。 - 对
vla.cpp做最小 A/B:- 拉取并固定一个 commit;
- 下载公开 SmolVLA GGUF;
- 跑
vla-cli单张图像 smoke test; - 对比输出 shape、action statistics、latency;
- 再判断是否转换自有 checkpoint。
llama.cpp暂作为 LLM 本地 provider 和 ggml/GGUF runtime 参考,不直接承担 SmolVLA 全链路迁移。- RK3588 继续用于端到端接口和硬件输入验证;若要追求实时,优先考虑模型结构压缩、prefix 蒸馏和 denoise step 减少。
参考资料
agent-llm-vla/docs/architecture.mdagent-llm-vla/docs/contracts.mdagent-llm-vla/docs/development_plan.md/home/sakura/OrangePi/rk3588_smolvla/README.mdhttps://github.com/lenLRX/llama_orangepihttps://github.com/Burtinsaw/GGML-CANNhttps://github.com/ggml-org/llama.cpp/blob/master/docs/backend/CANN.mdhttps://github.com/VinRobotics/vla.cpphttps://arxiv.org/abs/2606.08094
第四周(2026-07-27 ~ 2026-07-31)
本周目标
本周工作从上一周的 SG2002 ACT 非 JPU baseline 继续向三个方向收口:
- 评估 LicheeRV Nano / SG2002 原生 Linux 上的 JPEG 硬解码路线,判断 JPU 是否适合作为当前 ACT 输入链路的短期优化主线。
- 验证 C906 / SG2002 上
libjpeg-turbo的 RISC-V 向量化可行性,明确 RVV 1.0、RVV 0.7.1 和 C fallback 的边界。 - 调研并验证 KWS 语音命令识别路线,为后续 Agent/VLA 的语音入口提供可部署方案。
本周没有完成 StarryOS 侧 JPU 硬解码验证,因此这里不把 StarryOS JPU 写成已跑通结果。JPU 相关结论只限于 LicheeRV Nano 原生 Linux 与参考 SDK 路线的可行性评估。
LicheeRV Nano JPU 路线评估
本周通过原生 Linux 系统和 LicheeRV Nano SDK 参考实现,重新分析了 SG2002 上 JPEG 硬解码是否适合直接接入 ACT 图像输入链路。测试和源码走读后,当前判断是:JPU 方向仍有长期价值,但不适合作为本周继续压缩 ACT 端到端时延的短期主线。
主要原因如下:
- SDK 示例路径不是一个轻量的“单张 JPEG 到 RGB/YUV buffer”接口,而是绑定了较完整的 CVI/JPU/VDEC buffer 管理、stream submit、frame buffer 注册和输出拷贝流程。
- 原生 Linux 路线中
send/ stream 提交阶段开销偏大,短期内难以确认实际慢点来自硬件解码、驱动同步、buffer 管理还是用户态封装。 - 当前 ACT 链路只需要连续小图 JPEG 解码;如果引入完整 VDEC/VBPool/多 channel 框架,工程范围会明显扩大,且对 StarryOS 迁移帮助有限。
- JPU 输出通常是 YUV/planar buffer,后续仍需要颜色空间转换、resize、cache 同步和物理连续内存管理;这些开销如果处理不好,可能抵消硬解码收益。
- StarryOS 侧目前没有完成与 Linux 参考序列一致的硬解码验证,不能把 Linux 示例成功等价看成 StarryOS 已可用。
因此当前 JPU 结论是:保留为后续硬件输入链路优化方向,但本周不再把它作为默认性能优化主线。后续如果继续做,应先实现最小化单帧 path:固定 JPEG bitstream buffer、固定输出 buffer、复刻 Linux JPU_DecOpen -> JPU_DecGetInitialInfo -> JPU_DecRegisterFrameBuffer -> JPU_DecStartOneFrame -> wait irq/status 的寄存器序列,再与 libturbojpeg 做同图 checksum 和耗时对比。
RVV0.7 + C 加速 JPEG 解码
本周进一步验证了 libjpeg-turbo 在 C906 / SG2002 上的 RISC-V SIMD路线。结论是:不能直接使用当前上游 RVV 1.0 版本,短期可行路线是围绕 RVV 0.7.1 和 C 实现做定向移植。
RVV 1.0 直接上板失败
尝试替换较新的 libjpeg-turbo 动态库后,StarryOS 侧运行出现 IllegalInstruction。结合 C906 指令集特性判断,原因是 SG2002 的 C906 核心支持的是 RVV 0.7.1,而不是上游新版本常用的 RVV 1.0 指令编码。因此直接编译最新版 libjpeg-turbo 的 RVV 1.0 SIMD 代码不可行。
RVV rollback 风险
本周也分析了 rvv-rollback 和平头哥 GCC 10.2 工具链路线。当前判断是:
- 如果上游 RVV 1.0 代码只使用 LMUL=1/2/4/8 这类 0.7.1 原生支持的分组,自动翻译风险较低;
- 如果热点代码大量依赖 fractional LMUL,自动翻译会引入大量模拟和数据重排,性能可能反而低于纯 C;
- JPEG 解码涉及 8-bit 像素、采样、IDCT、颜色转换和交错/解交错操作,不能假设自动翻译一定有收益。
因此本周选择把可持续路线收敛为:参考早期 RISC-V / C906 RVV 0.7 分支,并保留 C fallback,在热点上手工改造,而不是盲目把 RVV 1.0 整体翻译到 RVV 0.7.1。
当前实测结果
在板端部署可运行的 libturbojpeg.so.0 后,ACT 同步链路继续采用:
turbojpeg + RVV resize + CVI TPU sync
当前稳定 baseline 如下:
| 阶段 | 典型耗时 |
|---|---|
| JPEG decode | 约 8.6-9.5 ms |
| RVV resize/interp | 约 3.3-5.0 ms |
| fill inputs | 约 0.3 ms |
| TPU inference | 约 51.6 ms |
| postprocess | 约 0.2 ms |
| pipeline | 约 65 ms/frame |
其中一次 20 帧测试结果为:
| 指标 | 数值 |
|---|---|
avg_image_decode_ms | 8.647 ms |
avg_resize_interp_ms | 4.993 ms |
avg_inference_ms | 51.611 ms |
avg_fill_inputs_ms | 0.334 ms |
avg_postprocess_ms | 0.216 ms |
avg_pipeline_ms | 65.801 ms |
100 帧测试中同步路径约为 avg_eval_wall_ms=65.294 ms,异步 split 路径约为 66.585 ms,说明在当前单核 SG2002 + StarryOS 环境下,继续做 TPU submit/wait overlap 没有收益。当前非 JPU 主线应固定为 libturbojpeg + RVV + sync,后续优化空间主要来自更细的 JPEG SIMD、减少内存拷贝和降低推理频率,而不是继续扩大异步调度复杂度。
KWS 调研与验证
本周围绕“前进、后退、左转、右转”等机器人控制语音命令,完成了三类 KWS 验证:官方 Google Speech Commands 路线、中文 TTS/DS-CNN 路线、SynTTS-Commands 数据集分析。
Google Speech Commands 路线
为了避开 Sophgo TDL 旧 sound-classification enum 路线的问题,本周实现了直接使用 cviruntime 的 KWS probe。该路径在主机侧完成训练和 TPU-MLIR 转换,在板端直接加载 cvimodel 推理。
当前四方向英文模型使用:
go, backward, left, right
严格四分类模型在验证集上达到约 92.32%。板端可加载 BF16 cv181x 模型,并通过 google_kws_runtime_probe 完成 log-mel 特征和 TPU 推理。测试中 go/left/right 能正确识别,但 backward 仍容易与 right 混淆,说明该模型可作为链路验证,但还不能直接作为最终控制入口。
板端耗时上,当前 C 前端仍是主要瓶颈:
| 阶段 | 典型耗时 |
|---|---|
| feature init | 约 42 ms |
| log-mel feature | 约 143 ms |
| TPU inference | 约 0.23 ms |
这说明 KWS 模型本体在 SG2002 TPU 上很轻,真正需要优化的是音频前端。后续应把当前朴素 DFT 改成 FFT/KissFFT 或复用更成熟的音频特征前端,并改成常驻进程,避免每次启动都重新加载模型。
中文 DS-CNN 路线
在 /home/sakura/KWS 中,本周进一步建立了中文 TTS 数据集和 DS-CNN 训练流程。当前数据配置如下:
| 项目 | 配置 |
|---|---|
| 采样率 | 16 kHz |
| 输入时长 | 1.2 s |
| 特征 | 40 mel bins |
| FFT | 512 |
| window / hop | 25 ms / 10 ms |
| 模型 | DS-CNN |
| 参数量 | 约 27k-28k |
当前有两种标签设计:
intent八分类:forward/back/left/right/front_left/front_right/back_left/back_right;text十五分类:前进/后退/左转/右转/向前/向后/向左/向右/...。
主要训练结果如下:
| 任务 | 最佳 epoch | val acc | test acc |
|---|---|---|---|
kws_dscnn_intent_v2_small | 28 | 70.56% | 74.44% |
kws_dscnn_text_v2_small | 27 | 71.11% | 73.33% |
混淆矩阵显示,短命令之间仍有明显混淆,例如 向左 容易被预测成 右转,向后 容易被预测成 向右。一次真实录音测试中,forward 被识别为 front_left,置信度约 0.741。因此当前中文 KWS 已经跑通训练、导出和测试闭环,但还不能直接用于真实控制。
SynTTS-Commands 数据集分析
本周还分析了 SynTTS-Commands-Official。该数据集对我们有架构和训练策略参考价值,但不能直接作为方向命令数据集使用。
原因是它当前公开命令集主要是媒体控制和唤醒词:
- 中文包括:播放、暂停、上一首、下一首、音量控制、接听电话、小爱同学等;
- 英文包括:Play、Pause、Resume、Next track、Volume up、Alexa 等;
- 不包含
前进/后退/左转/右转这类机器人运动命令。
它最有价值的结论是:中文 zero-shot 合成数据迁移到真实语音时召回会明显下降,而每类加入约 50 条真实样本后,真实测试效果会大幅提升。因此后续中文 KWS 不应只依赖 TTS 数据,必须采集目标麦克风、目标环境下的少量真实样本做 fine-tune。
当前结论
- LicheeRV Nano / SG2002 的 JPU 硬解码路线仍值得后续研究,但当前 Linux SDK 路径过重,
send和 buffer 管理开销不透明,短期不适合作为 ACT 输入链路优化主线。 - SG2002/C906 不能直接使用上游 RVV 1.0
libjpeg-turboSIMD;当前应沿 RVV 0.7.1 + C 定向优化路线推进。 libturbojpeg + RVV + sync已经是当前 ACT 非 JPU 稳定 baseline,约 65 ms/frame,其中 TPU 推理约 51.6 ms,占主要部分。- KWS 侧已经跑通 Google KWS、中文 TTS/DS-CNN 和板端 cviruntime probe,但真实可用性还受音频前端耗时、真实录音样本不足和短命令混淆影响。
- 后续若要接入 Agent/VLA,推荐优先做“常驻 KWS 进程 + 真实样本 few-shot + FFT 特征前端”,而不是先扩大模型规模。
下周计划
- 继续压缩 KWS 音频前端,把当前朴素 DFT 特征提取替换为 FFT 实现,并测量常驻进程下端到端延迟。
- 录制每类至少 50 条真实中文方向命令样本,重新训练 DS-CNN,并重点观察
前进/左转/右转/后退的混淆矩阵。 - 保留
libturbojpeg + RVV + sync作为 SG2002 ACT 默认 baseline,后续只做小范围可量化优化。 - 如果继续研究 JPU,先在 Linux 侧拆出单帧最小 path,再决定是否迁回 StarryOS,而不是直接移植完整 VDEC/VBPool 框架。
蒋玉月 · StarryOS SG2002 TPU 推理
负责 SG2002 (LicheeRV Nano) 平台上的 StarryOS 内核移植和 YOLO TPU/NPU 硬件推理加速。
- 内核:StarryOS (Rust 宏内核, RISC-V 64)
- 平台:算能 SG2002 (0.5 TOPS NPU)
- 目标:四语言 (C/C++/Python/Rust) TPU 推理 < 50ms
第 1 周(2026-07-13 ~ 2026-07-19)
蒋玉月 · StarryOS SG2002 TPU/NPU 推理加速 阶段声明:从 CPU 推理迈向四语言 TPU 硬件推理全线通过
一、本周工作总览
| 日期 | 主题 | 结果 |
|---|---|---|
| 07-13 | TGOSKits 环境搭建 + StarryOS 内核构建 | ✅ 内核 13MB,含 TPU 驱动 |
| 07-14 | FIT image 启动机制 + SD 卡部署 + Rust TPU 上板 | ✅ 启动成功,Rust 41ms |
| 07-15 | C / C++ / Python v4 TPU 推理全线实现 | ✅ 四语言全部通过,检出对齐 |
| 07-15 | 性能终榜 + Benchmark 报告 | ✅ 最高 358x 加速,产出已归档 |
二、关键成果
2.1 StarryOS 内核启动与四语言 TPU 推理
TGOSKits StarryOS 通过 FIT image + bootm 成功启动,/dev/cvi-tpu0 正常挂载。在此基础上,C / C++ / Python / Rust 四语言 TPU 推理全部实现并上板验证通过。
Python 侧基于 raw ctypes 桥接 libcviruntime.so,零编译依赖,纯 Python 驱动 TPU 硬件。配合 C 加速预处理(resize 2200x 加速)和 IoU NMS 后处理,v4 版本检出结果与 C++/Rust 完全对齐。
2.2 全引擎性能终榜
| 系统 | 引擎 | 语言 | 推理耗时 | 加速比 | 备注 |
|---|---|---|---|---|---|
| TGOSKits StarryOS | TPU | C | 39.6ms | 358x | 11KB |
| TGOSKits StarryOS | TPU | C++ | 40.0ms | 355x | 直连 CVI_NN |
| TGOSKits StarryOS | TPU | Python | 40.0ms | 355x | sg2002_tpu 包 |
| TGOSKits StarryOS | TPU | Rust | 41ms | 346x | akars-validator |
| Sipeed Linux | TPU | Python | 200ms | 71x | cvitek_tpu |
| StarryOS bare-metal | CPU | C++ | 14.19s | 1x (基准) | — |
| Sipeed Linux | CPU | C++ | 14.17s | 1x | yolo_infer_cpp |
| Sipeed Linux | CPU | Python | 25.1s | 0.6x | yolo.py |
基准: C++ CPU on StarryOS bare-metal (14.19s);加速比 = 14.19s / 推理耗时
检出精度三引擎 100% 对齐:C++ / Rust / Python v4 均检出 1 框,置信度 0.969,坐标 (261, 263, 371, 377)。
2.3 Python v4 优化历程
| 版本 | Raw Forward | +memcpy | 每图总耗时 | 检出精度 | 改进 |
|---|---|---|---|---|---|
| v3 | 60ms | — | 1.57s | ❌ 11 重复 | — |
| v4 | 51.6ms | — | 0.47s | ✅ 1 精准 | +NMS, +安全退出 |
| v4+opt | 40ms | 44.5ms | 0.10s | ✅ 1 精准 | +Raw, +缓存 |
2.4 全流程耗时拆解
| 引擎 | 模型加载 | 预处理 | TPU Forward | 后处理 | 总计 |
|---|---|---|---|---|---|
| C++ | 3375ms | 308ms | 40ms | <1ms | 3723ms |
| Rust | — | 474ms | 41ms | 7ms | 522ms |
| Python v4 | — | 338ms | 52ms | 68ms | 458ms |
C++ 模型加载含文件 I/O。Rust / Python 预处理含 JPEG 解码 + resize + letterbox。 v4+opt 使用预缓存 .int8 跳过预处理,TPU Forward + memcpy 仅 44.5ms,每图总耗时约 100ms。
三、产出
全部代码已提交至 ACT-Runtime:
ACT-Runtime/
├── python/sg2002_tpu/ # Python TPU 包 (engine / decode / cli)
├── c/ # C TPU 推理 (11KB)
├── cpp/ # C++ TPU 推理 (15KB)
├── rust/ # Rust TPU 推理 (含摄像头/检测/TPU)
├── benchmark_report.md # 性能 Benchmark 报告
└── BUILD.md # 交叉编译指南
- sg2002_tpu:engine.py + decode.py + cli.py,~150 行核心代码
- StarryOS 内核:13MB,含 TPU 驱动,SD 卡可启动
- 四语言二进制:C (11KB) / C++ (15KB) / Python (15KB) / Rust (860KB)
四、下周计划
核心目标:端到端网球检测 → 捡起,初步调试环境搭建。
- 完善性能对比:多图片批量 Benchmark(avg / p95 / fps),形成完整性能报告
- 摄像头实时采集:V4L2 接入 + TPU 推理 pipeline 联调
- 机械臂控制接入:SO101 驱动适配,基础抓取动作
- 检测→抓取闭环:检测结果 → 坐标变换 → 机械臂指令,端到端联调
五、Python TPU 推理关键技术突破
5.1 背景
板上 Python 3.11 是 RISC-V musl 交叉编译版,无 pip、无 build 工具链,无法安装任何 Python 包,也无法编译 C 扩展。要把 Python 代码跑在 TPU 上,逐一突破了以下关卡。
5.2 突破一:Python ↔ C 库桥接
常规方案 PyBind11 / Cython 都需要交叉编译,在板上完全不可行。最终采用 raw ctypes:ctypes.CDLL("libcviruntime.so") 直接加载 Cvitek TPU 运行时库,零编译依赖。
RISC-V 64 + musl 上 ctypes 的 argtypes/restype 存在结构体传参 ABI 不兼容,改用 struct.unpack 手动解析 CVI_TENSOR(88 字节结构体)内存布局,安全绕过。
5.3 突破二:预处理加速 2200 倍
纯 Python 做 resize + letterbox 耗时 11 秒,完全不可接受。编写 C 加速库 preprocess_ops.so (5.8KB),双线性插值 resize + letterbox + RGB→CHW planar 转换,交叉编译为 RISC-V musl 共享库,Python 通过 ctypes 调用,耗时降至 5ms。
5.4 突破三:NMS 后处理从 11 框到 1 框
v3 版本直接输出 TPU 原始结果 [1,5,8400] FP32,同一物体被检出 11 个重复框。v4 实现标准 IoU NMS(阈值 0.45):置信度过滤 → 排序 → 逐框 IoU 抑制,最终精准检出 1 框,与 C (39.6ms) / C++ (40.0ms) / Rust (41ms) 输出完全对齐。
5.5 突破四:内核启动机制
StarryOS 是 Linux-musl PIE 而非 bare-metal ELF,不能用 go 0x80200000 跳转。通过 mkimage 打包 kernel + DTB → FIT image,U-Boot bootm 启动,TPU 驱动 /dev/cvi-tpu0 正常挂载,打通最后一道系统壁垒。
5.6 结果
Python TPU Raw Forward 40.0ms(25 fps),与 C (39.6ms) / C++ (40.0ms) / Rust (41ms) 持平,瓶颈在 TPU 硬件而非 Python 解释器。含 JPEG 预处理全流程 458ms;使用预缓存 .int8 跳过预处理后,TPU Forward + memcpy 仅 44.5ms,每图总耗时约 100ms。
第 2 周(2026-07-20 ~ 2026-07-26)
蒋玉月 · StarryOS SG2002 TPU/NPU 推理加速 阶段声明:单帧推理→端到端管线→控制层迁移,进入板上闭环联调阶段
一、本周目标
对接李明涛的 UVC 驱动打通摄像头→TPU 推理全链路,参照 AKA-00 开源方案移植机器人控制层,实测对比两款模型的板上性能。
二、关键成果
2.1 管线性能演进:v2 → v7
| 阶段 | v2(基线) | v5(上周) | v7(当前) | 改善 |
|---|---|---|---|---|
| Camera | 300ms | 189ms | 95ms | 3.2x |
| Preprocess | 235ms | 146ms | 96ms | 2.4x |
| TPU Forward | 51ms | 70ms | 40ms | 硬件极限 |
| NMS | 4ms | 4ms | 2ms | 2x |
| 总计 | 590ms | 409ms | 233ms | 2.5x |
| FPS | 1.7 | 2.4 | 4.3 | — |
v7 相比 v2 总耗时降至 1/2.5,FPS 翻倍。主要收益来自:Camera(李明涛驱动优化 + 取帧策略改进)、Preprocess(零拷贝 + 浮点直写 TPU buffer)、NMS(C 实现精简)。
2.2 李明涛:StarryOS USB UVC 驱动
在 tgoskits 上合入了 UVC 驱动的核心模块:
- uvc 驱动:
uvc_camera.rs,含 YUYV 格式支持和 DWC2 USB Host 初始化 - V4L2 框架:按 Linux
include/uapi实现设备节点层,/dev/video0正常挂载 - vivid 虚拟驱动重构至
drivers/media/vivid/ - 用户态工具
v4l2-test:v4l2-ctl 交叉编译 + 3 个 V4L2 采集/测试程序,run.sh一键 build/deploy/sdcard
当前 Camera 取帧已从最初 300ms 优化至 95ms(v7),对比 Linux 端 10ms 仍有差距,驱动层持续优化中。
2.3 AKA-00 机器人参考架构分析
深度分析了 chenlongos/AKA-00 的完整技术栈:
- 硬件架构:SG2002 + ESP32-C3(底盘 PWM PID) + ZP10S/STS3215 舵机(UART)
- 控制算法:5 状态 FSM(chase→position→grab→bucket→release)+ P 比例差速控制
- 通信协议:ESP32 UART 帧协议(0xAA 0x55 + checksum),ZP10S ASCII 协议
- Web 前端:React + TypeScript,支持方向键/RC 摇杆/重力感应/模型商店
2.4 控制算法迁移
将 AKA-00 控制算法迁移至 StarryOS,新增文件:
pipeline/
├── state_machine.py # 5状态FSM + PID差速控制
├── motor_driver.py # ESP32 UART协议 (Mock + TtPid)
├── servo_driver.py # ZP10S / STS3215 舵机
├── hunter.py # 主控循环(TPU推理→状态机→PID→电机)
├── web_server.py # 内置Web遥控(纯Python,零外部依赖)
├── terminal_debug.py # 终端可视化调试
└── robot.py # 统一入口(debug/mock/web/run/test 五命令)
PC mock 验证:5 状态全通,PID 差速输出正确,10 帧确认抓取机制正常。
2.5 板上模型对比
AKA-00 Linux 系统上,两款 cvimodel 各跑 200 次 TPU Forward:
V2 avg=39.6ms p50=39.5ms min=39.5ms
AKA-00 avg=188.5ms p50=188.4ms min=188.3ms
| 模型 | Forward | 内存占用 | Anchors | 检出置信度 |
|---|---|---|---|---|
| V2 | 39.6ms | 2.2MB | 8,400 | 0.95-0.97 |
| AKA-00 | 188.5ms | 10.7MB | 27,600 | 0.85 |
V2 快 4.8 倍,因为 anchor 数为 AKA-00 的 1/3,推理负载更低。注意此对比使用的是 AKA-00 自带的 cvimodel(27,600 anchors),与 2.6 节中在 Linux 端运行 V2 模型(40ms)不是同一个模型。检出置信度更高得益于 YUYV native 路径(无 OpenCV JPEG 压缩损失)。
2.6 StarryOS v7 vs AKA-00 Linux
| 阶段 | StarryOS v7 | AKA-00 Linux | 备注 |
|---|---|---|---|
| Camera | 95ms | 10ms | Linux UVC 驱动更成熟 |
| Preprocess | 96ms | 120ms | C 零拷贝 vs OpenCV |
| TPU Forward | 40ms | 40ms | TPU 硬件,与 OS 无关 |
| NMS | 2ms | 4ms | — |
| 总计 | 233ms | 174ms | 差距 1.3x |
| FPS | 4.3 | 5.7 | — |
关于 StarryOS vs Linux 速度对比的更正:此前曾表述 “StarryOS TPU 推理比 Linux 快”,该结论存在误导。本周在 AKA-00 Linux 板上实测验证后发现:
- TPU 纯 Forward 耗时与 OS 无关。同一模型(V2 cvimodel)在 StarryOS 和 AKA-00 Linux 上均为 40ms。TPU 是独立硬件加速器,推理速度由模型结构决定,不受 Host OS 影响。
- 此前 Linux 端 200ms 的数据来自 Sipeed Buildroot + cvitek_tpu SDK 旧版本,差距源于 SDK 调用链路。
- StarryOS 端 Camera 95ms 对比 Linux 端 10ms,是当前总耗时差距(1.3x)的唯一来源。Preprocess 和 NMS 环节 StarryOS 反超。
2.7 预处理优化历程
| 版本 | 方案 | Pre | TPU | FPS | 关键改进 |
|---|---|---|---|---|---|
| v2 | malloc 分离版 | 235ms | 51ms | 1.7 | 基线 |
| v5 | 浮点 + 直写 TPU | 146ms | 70ms | 2.4 | 零拷贝写入 TPU buffer |
| v7 | 零拷贝 + 精简路径 | 96ms | 40ms | 4.3 | 消除中间 buffer + NMS 精简 |
三、产出
全部代码位于 ACT-Runtime:
pipeline/
├── state_machine.py # 5状态FSM + PID差速控制
├── motor_driver.py # ESP32 UART协议 (Mock + TtPid)
├── servo_driver.py # ZP10S / STS3215 舵机
├── hunter.py # 主控循环(TPU推理→状态机→PID→电机)
├── web_server.py # 内置Web遥控(纯Python)
├── terminal_debug.py # 终端可视化调试
└── robot.py # 统一入口(debug/mock/web/run/test 五命令)
board_tools/
├── model_compare.py # 双模型对比脚本
└── collect_data.py # 数据采集脚本
dataset/
├── images_png/ # 202张待标注PNG(50MB)
└── images_yuv/ # 原始YUYV帧(119MB)
四、下周计划
- 跟进 DQBUF 驱动优化,StarOS 端到端闭环上线,目标 5fps
- 接入 ESP32 电机 + 舵机真实硬件,验证状态机 + PID 控制
第 3 周(2026-07-27 ~ 2026-08-01)
蒋玉月 · StarryOS SG2002 TPU/NPU 推理加速 阶段声明:控制层落地 + 真机联调,管线突破 5fps,电机遭遇环境差异卡点
一、本周目标
- 跟进李明涛 DQBUF 驱动优化,端到端闭环上线,目标 5fps
- 接入 ESP32 电机 + 舵机真实硬件,验证状态机 + PID 控制
- 板上实测全链路:Camera → TPU 检测 → 运动控制 → 夹取
二、关键成果
2.1 管线性能:v7 → v8,突破 5fps
| 指标 | v7(上周) | v8(本周) | 变化 |
|---|---|---|---|
| TPU Forward | 40ms | 52ms | 慢 12ms |
| 整管线延迟 | 233ms | ~183ms | 快 21% |
| 稳态帧率 | 4.3 fps | 5.2-5.5 fps | +22% |
| 检测置信度 | — | 0.50-0.79 | — |
达成上周 5fps 目标。Camera 从之前的 isochronous 传输秒挂到稳定 100ms 出帧,Preprocess 和 NMS 沿用 C 后端零拷贝路径。
2.2 李明涛:CrabUsb 架构升级
本周李明涛完成了 StarryOS USB 栈的重大架构变更:
旧: StarryOS usbfs(中断已占用) ✗ sg200x-bsp → 中断冲突 → 轮询超时 255ms
新: StarryOS usbfs(事件循环) ✓ CrabUsb → 合法注册中断 → 100ms 稳定
效果:CrabUsb 与内核 USB 栈共享同一中断体系,不再是“绕过“而是“融入“。Camera 取帧从之前偶尔 255ms 空转变为稳定均匀的 100ms。下一步优化方向:usbfs 事件循环中给 UVC 开低延迟通道(中断直通 + buffer 预分配),目标从 100ms → 接近 Linux 10ms。
内核版本演进:
| 版本 | 日期 | 大小 | 说明 |
|---|---|---|---|
| boot.sd.old_20260721 | 7/21 | 12.5 MiB | 原始版本 |
| boot.sd.old_20260727 | 7/22 | 12.85 MiB | 第一次更新 |
| boot.sd (当前) | 7/25 | 12.78 MiB | 李明涛最新 |
v4l2-test 工具链就绪:1.tpg_check / 2.camera / 2.parser / 3.speed / capture,均 ~30KB 静态编译。
2.3 AKA-00 控制接口挖掘与真机驱动
从 chenlongos/AKA-00 仓库挖出完整硬件控制链:
SG2002
├── /dev/ttyS1 (UART1, 115200) → ESP32-C3 → DRV8833 → N20 TT马达×2
│ 协议: 0xAA 0x55 <cmd> <len> <payload> <chk>
│
└── /dev/ttyS2 (UART2, 115200) → 微雪控制板 → ZP10S舵机×3
协议: #<id>P<pulse>T<time>!
确认 StarryOS 板端 /dev/ttyS0/1/2/3 全部存在,驱动可用。
2.4 全自动追球管线 (real_pipeline.py)
实现完整状态机:
Camera(100ms) → Preprocess(C) → TPU(52ms) → NMS(C)
→ 无目标: 原地右转搜索
→ 球远(far): 快速前进 + 方向修正
→ 球中(mid): 慢速接近 + 方向修正
→ 球近(near): 停车 → 舵机夹取
2.5 板上实测
| 模块 | 状态 | 说明 |
|---|---|---|
| 环境 | ✅ | 内核/串口/Python/C 库/模型全部就位 |
| Camera | ✅ | 首日 isochronous 秒挂,CrabUsb 新内核后稳定 100ms 出帧 |
| TPU | ✅ | ~52ms Forward,检出置信度 0.50-0.79 |
| 控制逻辑 | ✅ | GRAB/SEARCH 状态机自动切换正常 |
| Servo 舵机 | ⏳ | 设备在位,未实测夹取 |
| Motor 电机 | 🔴 | handshake 通过但轮子不转(见 2.6) |
| WiFi | ❌ | N24250 模块未接线 |
2.6 Motor — 本周最大卡点(环境差异)
TtPidDriver协议握手返回 OK,但电机不转- 定位到软件 bug:raw I/O fallback 路径
_send_cmd调用reset_input_buffer(),此方法在 file object 上不存在,AttributeError被except: pass静默吞掉 → 数据从未发出 - 串口波特率默认 38400,需
stty -F /dev/ttyS1 115200修正 - 关键发现:同一份
motor_driver.py代码在李明涛的板子上电机正常转动,用户板子只 handshake 通过但轮子不动 → 驱动逻辑本身正确,问题在板端环境差异 - 待排查:两边内核版本、串口驱动行为、电平/接线、ESP32-C3 固件版本差异
三、产出
| 类型 | 内容 |
|---|---|
| 代码 | real_pipeline.py — 真机主程序:Camera→TPU→追球→夹取 全自动 |
| 代码 | motor_driver.py — ESP32-C3 电机 UART 驱动(Mock + Real 双模式) |
| 代码 | servo_driver.py — ZP10S/STS3215 舵机 UART 驱动(Mock + Real 双模式) |
| 文档 | REAL_MACHINE_GUIDE.md — 完整操作指南(接线/测试/故障排查) |
| GitHub | jiangyuyue111/sg2002_yolo_inference — 初始提交(86 文件 + 贡献者说明) |
| ACT-Runtime | chenlongos/ACT-Runtime — CrabUsb + Isoch 架构升级 + 性能数据更新 |
| SD 卡 | 全部 pipeline 文件 + 指南已部署到 ext4 分区 |
四、下周计划
- 🔴 电机环境差异排查(最高优先):逐项对比两边内核版本、串口驱动、ESP32-C3 固件,必要时直接裸协议
echo到/dev/ttyS1排除 Python 层干扰 - 🟡 舵机夹取实测:验证 ZP10S 夹爪完整抓球动作闭环
- 🟡 pyserial 迁移:替换 raw file I/O fallback,消除
PYTHONPATH手动设置 - 🟡 WiFi 模块接入:焊接 N24250 模块,实现无线调试/控制
- Camera 性能优化:配合李明涛 usbfs 低延迟通道方案,目标 100ms → 接近 Linux 10ms
杨铮
Octos 任务编排层 / 最小工具闭环验证 / 轮足双臂技能接口前置调研
基本信息
| 项 | 内容 |
|---|---|
| 姓名 | 杨铮 |
| 方向 | Octos 编排层、任务分解、技能调用、状态监听、重试闭环 |
| 项目 | 嘲风轮足双臂机器人 |
| 当前阶段 | 阶段 1:Octos 最小 demo 跑通与技能接口前置规范 |
| 验证工作区 | /Users/ken/robot-octos-demo |
| 归档目录 | docs/src/yangzheng/ |
| 周期 | 2026-07 ~ 2027-02 |
文档入口
最新进展
截至 2026-07-19:
- 已确认
octos 2.0.0可在本机运行,并完成本地技能robot-pick-skill的发现与直接调用验证; - 已在
/Users/ken/robot-octos-demo内完成一次真实octos chat工具闭环,模型可把中文请求路由到pick_object; - 已确认 demo 工作区不是顶层 Git 仓库,而是“系统 Octos + 本地 skill + 嵌套上游源码副本”的混合形态;
- 已在
octos-src内完成cargo check --locked -p octos-cli静态构建检查; - 已识别当前最主要的工程问题是项目级
data-dir与全局 provider 配置继承关系不稳定。
当前判断
当前已验证的是 Octos 编排最小闭环,不是轮足真机移动、操作或视觉判定闭环。下一步应该把这次最小 demo 的成功路径抽象成三类接口需求:
- 移动技能接口;
- 操作技能接口;
- 复合任务接口。
在接口稳定前,不应直接把 demo 成功等同于真机编排已完成。
第 2 周(2026-07-14 ~ 2026-07-19)
杨铮 · Octos 任务编排层 / 最小工具闭环验证 阶段声明:先跑通 Octos 最小 demo,再向移动 / 操作 / 复合任务接口规范收口
一、本周工作总览
| 日期 | 主题 | 结果 |
|---|---|---|
| 07-19 | 验收目录与项目形态核查 | 已完成 |
| 07-19 | 本地 skill robot-pick-skill 直接执行验证 | 已完成 |
| 07-19 | octos chat 中文请求到 pick_object 的真实闭环验证 | 已完成 |
| 07-19 | octos-src 中 octos-cli 构建检查 | 已完成 |
| 07-19 | 运行问题归因与下一步接口收敛 | 已完成 |
二、关键成果
2.1 最小 Octos demo 已跑通
在 /Users/ken/robot-octos-demo 中,已经完成以下闭环:
中文自然语言请求
→ octos chat
→ 模型选择 pick_object
→ 本地 skill 执行
→ 工具结果返回
→ 自然语言答复
成功案例中,用户请求“帮我把球捡起来,在地上”,系统实际调用了:
pick_object(object="球", location="地上")
最终返回“已经帮你把球从地上捡起来了!”。
2.2 项目形态已核清
本次用于验证的工作区不是单一 Rust 工程,而是:
- 顶层 demo 目录
/Users/ken/robot-octos-demo; - 顶层本地技能目录
.octos/skills/robot-pick-skill; - 系统已安装的
octos 2.0.0; - 嵌套上游源码副本
/Users/ken/robot-octos-demo/octos-src。
这意味着当前阶段的主要运行路径是:
系统 Octos
+ 项目内本地 skill
+ 项目内 data-dir / config
而不是先在顶层 demo 目录重新构建一个全新的 octos 二进制。
2.3 源码级检查通过
在 octos-src 中已执行:
cargo check --locked -p octos-cli
最终输出:
Finished `dev` profile [unoptimized + debuginfo] target(s) in 5m 03s
这说明当前附带的上游源码副本至少在 octos-cli 维度能够完成静态构建检查。
三、问题与判断
3.1 当前主要问题不是技能失效,而是配置继承
当 octos chat 使用项目内新的 --data-dir 运行时,第一次验证失败,错误为:
no LLM provider configured
在显式追加:
--config "$HOME/.config/octos/config.json"
之后,闭环验证成功。
当前更合理的判断是:
- 问题点在项目级运行态没有稳定继承全局 provider 配置;
- 问题点不在
robot-pick-skill本身; - 问题点也不在
octos chat基本调用链路。
3.2 运行告警说明后续工程化仍需补齐
成功运行时仍出现以下告警:
- legacy global skill directory is no longer scanned;
- local plugin manifest 缺少 sha256,被标记为 unverified plugin;
- tool count 较高,可能影响部分模型稳定性。
这些问题没有阻止本周 demo 成功,但都属于后续如果要把 demo 演化成长期维护项目时必须处理的工程化项。
四、对杨铮阶段任务的意义
这次验证已经足够支撑阶段 1 的前半部分:
- Octos 部署与最小工具调用 demo 已跑通;
- LLM 可以完成“中文请求 -> 本地技能调用”的基本编排;
- 可以开始从 demo 成功路径抽象技能接口规范。
当前还没有直接完成的内容是:
- 移动命令颗粒度定义;
- 移动结果字段设计;
- 坐标系约定;
- 操作技能与复合任务统一 schema。
因此,下一步不应继续重复做“能不能跑通 Octos”,而应转向接口定义与替换路径设计。
五、下周计划
- 以当前
pick_objectdemo 为基线,整理移动 / 操作 / 复合任务三类技能 schema 草案; - 补一份“项目级 data-dir / profile / provider 继承关系”运行说明,减少重复踩坑;
- 评估本地 skill manifest 中 sha256、校验与 profile 级安装方式;
- 把 mock skill 的成功路径抽象成未来真实 VLA / 机器人技能的统一输入输出契约;
- 对接阶段 2 所需的 planner 形态,明确是单次 function-call 序列还是状态机驱动重规划。
六、证据位置
/Users/ken/robot-octos-demo/reports/evidence/project-initial-audit.txt/Users/ken/robot-octos-demo/reports/evidence/environment.txt/Users/ken/robot-octos-demo/reports/evidence/octos-chat-robot-pick.txt/Users/ken/robot-octos-demo/reports/evidence/octos-chat-robot-pick-config.txt/Users/ken/robot-octos-demo/reports/evidence/cargo-check-octos-cli.txt
01 · Octos 最小工具闭环与目录验收
日期:2026-07-19
一、背景
本轮工作的目标不是直接验证真机动作,而是为“杨铮负责的 Octos 编排层”先拿到一个可信的最小成功样本:确认 Octos 可以在本机跑通一次从中文请求到本地工具调用的真实闭环,并梳理这个 demo 对后续技能接口设计的意义。
本次实际验收工作区为:
/Users/ken/robot-octos-demo
最终归档目录位于:
/Users/ken/chaofeng/docs/src/yangzheng/
二、核查过程
1. 先确认项目形态
核查后确认:
/Users/ken/robot-octos-demo顶层不是 Git 仓库;- 顶层存在本地技能目录
.octos/skills/robot-pick-skill; - 系统安装了
octos 2.0.0,命令位于/opt/homebrew/bin/octos; - 顶层还附带嵌套源码副本
octos-src。
这说明它是一个“系统 Octos + 本地 skill + 嵌套源码”的 demo 验收目录。
2. 先验证技能入口本身
直接执行:
printf '{"object":"ball","location":"floor"}' | skills/robot-pick-skill/main pick_object
返回:
success: true
Simulated robot successfully picked up ball from floor.
因此可以先排除“技能入口脚本损坏”的可能。
3. 再验证真实 octos chat
第一次在项目内使用新的 --data-dir 运行 octos chat 时,遇到错误:
no LLM provider configured
随后显式追加:
--config "$HOME/.config/octos/config.json"
第二次运行成功,模型调用了:
pick_object(object="球", location="地上")
最终返回中文答复“已经帮你把球从地上捡起来了!”。
4. 最后补一层源码检查
在 octos-src 中执行:
cargo check --locked -p octos-cli
检查通过,说明 demo 附带的上游源码副本至少在 octos-cli 维度是可构建的。
三、当前结论
1. 这次成功说明了什么
已经可以确认:
- 本机 Octos 环境可用;
- 本地 skill 发现机制可用;
- 中文自然语言到本地工具的最小闭环可用;
- 这个 demo 可以作为后续接口规范设计的起点。
2. 这次成功不说明什么
仍不能据此宣称:
- 真机移动编排已经完成;
- 真实 VLA 推理已经接入;
- 视觉判定与重试闭环已经完成;
- 复合任务 planner 已经稳定可用。
这次只是把“编排能不能起得来”这件事先做实了。
四、对后续工作的直接影响
后续更值得推进的方向有三项:
- 从
pick_object这种最小 schema 出发,设计移动 / 操作 / 复合任务三类接口; - 规范项目级
data-dir、config、profile 和 skill 安装关系; - 为未来 mock -> 仿真 -> 真机替换保留统一的工具输入输出契约。
五、相关证据
/Users/ken/robot-octos-demo/reports/evidence/environment.txt/Users/ken/robot-octos-demo/reports/evidence/project-initial-audit.txt/Users/ken/robot-octos-demo/reports/evidence/octos-chat-robot-pick-config.txt/Users/ken/robot-octos-demo/reports/evidence/cargo-check-octos-cli.txt