Compare commits

...
2 Commits
Author SHA1 Message Date
qing d8b601ab9a feat(bot4cj/scripts): 12 个 mtc DSL 源声明 Camera——录制免注入
动作脚本统一加入 Camera("cam0",640,480,30,8)(record_stand.py 已有),
编译产物自带 @Camera 块,pybot --record 直接可录,取代 v2 的
"注入式录制"变体方案。手写 .mt 保持不动(bot4cj 共享、美化格式)。
2026-08-15 19:48:16 +08:00
qing 286e632288 fix(pybot): 录制 spk.F 列恒 0——与模型 FIXED_OUTPUT 对齐
F2 方案下推理端 spk.F 固定输出 0(bins.FIXED_OUTPUT),而脚本真值
可达 1000Hz,保留真值产生"模型 0 vs 数据 1000"的评估伪影(14.5K)。
录制时写常量 0 消除伪影;spk.delay 微步录制下恒 10.0 已与模型一致。
data_v3(296MB 可复现录制产物)加入 .gitignore。
2026-08-15 19:48:09 +08:00
14 changed files with 47 additions and 0 deletions

No files matched your search

+3
View File
@@ -25,3 +25,6 @@ waf/certs/
# 运行时日志(HailoRT 等)
hailort.log
# 录制产物(可复现:mtc DSL → 编译 → pybot --record)
actpred/data_v3
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -33,6 +33,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -37,6 +37,9 @@ Servo("s8", -180, 0, 0, "pca9685-0", 7) # rf1
Servo("s9", 180, 0, 0, "pca9685-0", 8) # cam0
Servo("s10", 180, 0, 0, "pca9685-0", 9) # cam1
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
# stand:10ms(一个栅格步)内到位并保持;首行即目标值,无爬升
SetTo("s1", 45, 10)
SetTo("s2", 0, 10)
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -26,6 +26,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+3
View File
@@ -32,6 +32,9 @@ _SERVOS = [("s1", 90, 0), # rb0
for _name, _max, _ch in _SERVOS:
Servo(_name, _max, 0, 0, "pca9685-0", _ch)
# 录制源(pybot --record 需要 @Camera 块)
Camera("cam0", 640, 480, 30, 8)
_STAND = [45, 0, 45, 0, 45, 0, 45, 0, 90, 90]
def stand(dur=10):
+8
View File
@@ -17,6 +17,12 @@ from pathlib import Path
log = logging.getLogger("pybot.recorder")
# spk.F 列(动作契约列 10)与模型固定输出对齐:F2 方案下推理端该列恒为
# 常量 0(actpred/bins.py FIXED_OUTPUT),而脚本真实值可达 1000Hz——
# 保留真值会产生"模型 0 vs 数据 1000"的评估伪影。v3 起录制时写常量 0。
# spk.delay(列 11)无需处理:微步录制下恒为 10.0,与 FIXED_OUTPUT 一致。
SPK_F_COL = 10
class EpisodeRecorder:
"""录制 actpred 格式的 episode(images/*.jpg + actions.npy [+ imu.npy])
@@ -80,6 +86,8 @@ class EpisodeRecorder:
src = np.asarray(action_vec, dtype=np.float32).ravel()
n = min(len(src), self.action_dim)
vec[:n] = src[:n]
if self.action_dim > SPK_F_COL:
vec[SPK_F_COL] = 0.0
self._actions.append(vec)
if imu_vec is None: