- 将 7 个文档中的 mac 绝对路径链接(file:///Users/qingsong/...)转换为仓库相对路径, 并修正错误目标:aibox 入口 main.py → aibox.py、pymsg C++ 实现 → libmsg/inc/us/Msg.hpp、 bot4cj cpp/cnn → cuda - 主 README 补 liblogc 基础库条目与 confs2 归档说明,安装顺序补 ca - 新增 liblogc / libtry / confs2 / 3d / memdb README - 同步 db2 脚本迁移(db/create_sqlite3.sql → db2/scripts/)导致的失效引用
16 KiB
16 KiB
bot4cj — 机器人硬件脚本解析器
基于仓颉(Cangjie) 编程语言和 Linux I2C 接口的机器人动作脚本解析器。用一种矩阵式脚本来描述机器人的硬件构成与动作序列,解析后驱动真实硬件执行。
架构分层
┌──────────────────────────────────────────────────────────────┐
│ .mt 矩阵脚本(硬件定义 + 动作序列) │
├──────────────────────────────────────────────────────────────┤
│ MatrixParser(P.cj) — FSM 逐字符解析 → MatrixObject 链表 │
├──────────────────────────────────────────────────────────────┤
│ RobotStruct(r.cj) — 从矩阵对象构建硬件变量(createHardVars) │
│ MatrixVars_Hardware 基类 + 闭包回调: │
│ · build() → rise 回调(打开硬件、获取资源) │
│ · play() → things 回调(执行动作,参数/返回值均为 JsonValue) │
│ · free() → free 回调(释放资源) │
├──────────────────────────────────────────────────────────────┤
│ 硬件实现:hd/*.cj │
│ PCA9685(I2C 0x40, 50Hz PWM, 角度→脉宽 0.5~2.5ms) │
│ Servo(舵机:max/min/offset 校准 + 角度翻转) │
│ MPU6050(陀螺+加速度,±500°/s ±8g,后台 10ms 采样线程+卡尔曼) │
│ Speaker(正弦波发声,5ms 淡入淡出) │
│ fb.cj(外部硬件扩展口) │
├──────────────────────────────────────────────────────────────┤
│ 系统库:cpp/ + cuda/ │
│ libi2c4cj.so — I2C glibc 封装 + 20 槽锁数组 │
│ libmt4cj.so — FP32 矩阵运算(CPU / CUDA 二选一) │
│ libfft4cj.so — 基-2 Cooley-Tukey FFT │
│ libcnn4cj.so — Conv/Pool/GA-Pool/Flatten + Adam/Momentum │
│ libsnd4cj.so — WaveAPI / ALSA 音频播放 │
├──────────────────────────────────────────────────────────────┤
│ 数学/NN 库:math/*.cj │
│ Matrix1(二维矩阵)+ Tensor + 6 种激活函数 + Xavier 初始化 │
│ Nn1 全连接层(前向/反向/权重更新) │
│ Af(Sigmoid/Tanh/ReLU/Leaky_ReLU/Swish/Softmax) │
└──────────────────────────────────────────────────────────────┘
技术栈
| 层 | 技术 | 说明 |
|---|---|---|
| 应用层 | 仓颉 Cangjie | 主程序、解析器、机器人结构、数学库、HTTP 服务 |
| 系统层 | C / C++ | I2C 驱动、矩阵运算、FFT、CNN、音频 |
| 加速层 | CUDA(可选) | MODE=cpu/cuda 切换 |
| 脚本层 | .mt 矩阵脚本 |
硬件定义 + 动作序列 |
| 依赖包 | ctype4cj / pthread4cj / spi4cj / lua4cj | 仓颉官方扩展包 |
| 构建 | Makefile(C/C++ 共享库)+ cjpm.toml(仓颉包管理) | — |
目录结构
bot4cj/
├── src/
│ ├── main.cj # 入口:CLI 参数解析(-i/-o/--test)+ stdin 管道执行
│ ├── P.cj # 矩阵脚本解析器(FSM 逐字符解析)
│ ├── r.cj # RobotStruct + MatrixVars_Hardware 基类
│ ├── testCNN.cj # CNN 测试入口
│ ├── testCNN1.cj # 几何 CNN 测试
│ ├── hd/
│ │ ├── I2C.cj # I2C 封装 + 20 槽锁数组
│ │ ├── PCA9685.cj # PCA9685 舵机控制板(已标记由 Lua 替代)
│ │ ├── Servo.cj # 舵机:校准 + 角度翻转
│ │ ├── MPU6050.cj # MPU6050 陀螺+加速度+卡尔曼滤波
│ │ ├── snd.cj # 扬声器
│ │ ├── fb.cj # 外部硬件扩展
│ │ └── extern/
│ │ └── macro_ExternHardware.cj
│ ├── math/
│ │ ├── Matrix.cj # 二维矩阵(+运算符重载)
│ │ ├── Tensor.cj # 张量
│ │ ├── Af.cj # 6 种激活函数
│ │ ├── Ini.cj # Xavier/Kaiming 初始化
│ │ ├── nn.cj # 全连接层 Nn1
│ │ ├── nns.cj # 旧版神经网络(XNOR 门测试)
│ │ ├── cnn.cj # CNN 仓颉绑定
│ │ ├── pooling.cj # 池化
│ │ ├── flatten.cj # Flatten
│ │ ├── fft.cj # FFT 仓颉绑定
│ │ ├── kalman.cj # 卡尔曼滤波
│ │ └── Adam.cj # Adam 优化器
│ ├── cpp/ # C/C++ 系统库源
│ │ ├── I2C.c # I2C glibc 封装
│ │ ├── Matrix.cpp # CPU 矩阵运算
│ │ ├── fft1.c # FFT 单实序列
│ │ ├── fft.cpp # FFT 双实序列 + 基-2 Cooley-Tukey
│ │ ├── kalman.c # 卡尔曼滤波
│ │ ├── snd.cpp # 音频播放(WaveAPI/ALSA)
│ │ └── cnn/ # 纯 C++ CNN(Conv/Pool/GA-Pool/Flatten)
│ └── cuda/
│ ├── matrix.cu # GPU 矩阵运算 kernel
│ └── error.cuh # CUDA 错误检查宏
├── modules/ # Lua 硬件模块(ADS1115/ADS1256/PCA9685/SPI)
├── scripts/ # .mt 动作脚本(std/jump/lie-down/tilt-* 等)
├── test/ # C/Lua 测试脚本
├── docs/Reports/ # 深度分析报告
├── cjpm.toml # 仓颉包配置
├── Makefile # C/C++ 共享库构建
├── _set.sh # 编译(cjpm update + build)
├── _run.sh # 运行(stdin 管道)
├── compile.ps1 # Windows 编译脚本
├── run.ps1 # Windows 运行脚本
├── README.md # 旧版说明
└── README.robot.md # 本文件
快速开始
# 1. 编译 C/C++ 共享库(一次性)
make MODE=cpu # CPU 模式(默认)
# 或
make MODE=cuda # GPU 模式(需要 nvcc)
# 2. 编译仓颉程序
bash _set.sh
# 3. 运行动作脚本(stdin 管道)
cat scripts/std.mt | bash _run.sh
硬件要求:树莓派(aarch64)或其他 Linux I2C 设备。x86_64 开发板需自行验证 I2C 参数。Windows 暂不支持(依赖 glibc)。
CLI 参数
./bot # 从 stdin 读取 .mt 脚本执行
./bot --help # 打印帮助
./bot --test nn # 运行神经网络与门测试
./bot --test cnn # 运行 CNN 测试
./bot --test cnn1 # 运行几何 CNN 测试
./bot --test matrix_o # 解析 ss/test.mt 并保存为 ss/output.mt
./bot --test matrix_2 # 解析 ss/output.mt → 执行 → 再次保存
./bot -i model.json -o out.json # 加载/保存神经网络模型(DRL 预留)
.mt 脚本语法
行列式表格,每列以空格或制表符分隔,每行以分号 ; 结尾。
块结构
@BlockName
column1 column2 column3;
value1 value2 value3;
@
每个 @ 块由 @Name 行开始,@ 行结束。支持的块类型:
| 块 | 说明 |
|---|---|
@Alias |
列名别名(如 A → angle、F → frequency) |
@I2C |
定义 I2C 设备(name + path) |
@PCA9685 |
定义 PCA9685 舵机控制板(name + I2C 引用 + 地址) |
@MPU6050 |
定义 MPU6050 传感器(name + I2C 引用 + 地址) |
@Speaker |
定义扬声器(channels + sample_rate + volume + max_f + min_f) |
@Servo |
定义舵机(name + max + min + offset + controller + channel) |
@Action |
动作矩阵:列头为硬件变量的属性,行为每帧的参数 |
占位符
- 表示"沿用上一行同列的值",当前行该列不产生调用。
完整示例
@Alias
name alias;
A angle;
F frequency;
@
@I2C
name path;
i2c-0 /dev/i2c-0;
i2c-1 /dev/i2c-1;
@
@PCA9685
name I2C address;
pca9685-0 i2c-1 0x40;
@
@Speaker
name channels sample_rate volumn max_f min_f;
spk 2 48000 0.6 5000 -;
@
@Servo
name max min offset controller channel;
s1 90 - - pca9685-0 0;
s2 180 - - - 1;
s3 -90 - - - 2;
s4 -180 - - - 3;
@
@Action
s1.A s2.A s3.A s4.A spk.F spk.delay;
45 - 45 - 10 200; # 站立
90 - - - - 20; # 左转
@
执行流程
stdin.read()
↓
P.MatrixParser (FSM 逐字符解析)
↓
LinkedList<MatrixObject> 链表
↓
RobotStruct.createHardVars() # 按 @I2C/@PCA9685/@Servo/@Speaker/@MPU6050 构建硬件变量
↓
robot.active() # build():逐个硬件调用 rise 回调(打开 I2C、初始化 PWM 等)
↓
robot.run() # 逐行遍历 @Action 矩阵,每列调用对应硬件的 play() 回调
↓
robot.deactive() # free():倒序释放资源
play() 的输入输出均为 JsonValue,实现了硬件与脚本之间的统一通信协议。
已支持的硬件
PCA9685(I2C 舵机控制板)
- 地址:默认
0x40 - PWM 频率:50Hz(舵机标准 20ms 周期)
- 舵机脉宽映射:0°→0.5ms,180°→2.5ms
- 角度映射到 12 位 PWM 值(0-4095)
- 注意:PCA9685.cj 代码已标记"由 Lua 脚本取代",保留作备用
Servo(舵机)
- 支持
max/min角度限制与offset漂移校准 max < 0时自动翻转角度(反向安装的舵机)- 通过闭包回调与实际硬件(PCA9685/Lua 模块)解耦
MPU6050(6 轴传感器)
- 陀螺仪:±500°/s 量程
- 加速度计:±8g 量程
- 后台 10ms 采样线程(pthread_create + pthread_cancel)
- 卡尔曼滤波融合数据
- 已知问题:
ADDR_0与ADDR_1常量均为0x68(MPU6050.cj:14-15),第二个地址应改为0x69
Speaker(扬声器)
- 支持正弦波发声(指定频率
F+ 延时delay) - 5ms 淡入淡出,避免"咔哒"声
- 通道数/采样率/音量可在
.mt中配置 - 已知问题:
play()仅 sleep 指定延时,真实发声依赖底层 C++ 实现
机器人型号适配
Dashun 蜘蛛机器人(默认)
10 舵机 + 2 云台 + 扬声器,建模文件见 gopsc/Dashun:
| 舵机 | 关节 | 舵机 | 关节 |
|---|---|---|---|
| s1 | 左下水平 (rb0) | s6 | 右上垂直 (lf1) |
| s2 | 左下垂直 (rb1) | s7 | 左上水平 (rf0) |
| s3 | 右下水平 (lb0) | s8 | 左上垂直 (rf1) |
| s4 | 右下垂直 (lb1) | s9 | 云台1 (cam0) |
| s5 | 右上水平 (lf0) | s10 | 云台2 (cam1) |
可用脚本
scripts/ 目录下预写了多种动作脚本:
std.mt— 站立姿态jump.mt— 跳跃lie-down.mt— 趴下left-hand.mt/rght-hand.mt— 单手动作left-turn.mt/tilt-f.mt/tilt-b.mt/tilt-l.mt/tilt-r.mt— 转向与倾斜
构建
依赖
# 仓颉 1.1.3
# 仓颉官方扩展包:ctype4cj / pthread4cj / spi4cj / lua4cj
# libc / libpthread
# liblua-5.4(可选,Lua 硬件模块支持)
sudo ln -s /usr/lib/aarch64-linux-gnu/liblua5.4.so /usr/lib/aarch64-linux-gnu/liblua.so
sudo ln -s /usr/lib/x86_64-linux-gnu/liblua5.4.so /usr/lib/x86_64-linux-gnu/liblua.so
构建步骤
# 1. 构建 C/C++ 共享库
make MODE=cpu
# 产出:libi2c4cj.so libmt4cj.so libfft4cj.so libsnd4cj.so
# 2. (可选)构建 CNN
make libcnn4cj.so
# 3. (可选)CUDA 模式需 NVIDIA CUDA Toolkit
make MODE=cuda
# 4. 仓颉主程序
bash _set.sh
_set.sh 执行 cjpm update + cjpm build,自动解析 cjpm.toml 依赖。
运行
bash _run.sh scripts/std.mt
# 或
cat scripts/std.mt | bash _run.sh
_run.sh 以 cjStackSize=64MB / cjHeapSize=64MB 启动。
神经网络支持
项目内置了全连接层 Nn1(math/nn.cj)与 CNN(math/cnn.cj + cuda/):
- Nn1:多层感知机,支持前向传播、反向传播、权重更新
- CNN:Conv → ReLU → Pool → GA-Pool → Flatten → FC
- 优化器:Adam / Momentum
- 激活函数:Sigmoid / Tanh / ReLU / Leaky_ReLU / Swish / Softmax
- 初始化:Xavier / Kaiming
测试
./bot --test nn # 与门训练(2 输入 → 1 输出)
./bot --test cnn # CNN 前向/反向测试
./bot --test cnn1 # 几何分类 CNN 测试
DRL 预留(未完成)
main.cj 中预留了 DRL 流程(注释状态):加载预训练权重 → 执行动作 → 保存微调模型。通过 -i / -o 参数指定输入/输出路径。
安全与限制
I2C 总线保护
- hd/I2C.cj 内置 20 槽锁数组,多硬件共享 I2C 总线时自动互斥
- 每个 I2C fd 独立加锁,避免并发写入冲突
硬件关闭时机
MatrixVars_Hardware析构依赖仓颉 GC,不保证在确定性时机调用free()- 机器人使用
try/finally在 main.cj:80-87 中显式调用deactive(),确保硬件资源正确释放
线程安全
- MPU6050 采样通过
pthread_create启动后台线程 pthread_cancel依赖系统定义的取消点(sleep / 系统调用),可能在非安全点中断
平台支持
- ✅ Linux aarch64(树莓派)/ x86_64
- ❌ Windows(依赖 glibc)
已知问题
| ID | 描述 | 影响 |
|---|---|---|
| D1 | 仓颉 GC 不保证析构器调用,I2C fd 可能泄漏 | 长时间运行后 I2C 资源耗尽 |
| D2 | Speaker play() 仅 sleep,真实发声未接入 C++ |
扬声器无实际声音 |
| D3 | MPU6050 pthread_cancel 可能在非安全点中断 |
传感器数据不一致 |
| D4 | PCA9685 初始化被标记为"由 Lua 取代",但仍保留主路径 | 代码存在双实现 |
| D5 | _set.sh 会删除 a.out |
误删用户产物 |
| D6 | Softmax 雅可比矩阵实现错误(math/Af.cj) | NN 训练收敛异常 |
| D7 | Tensor 乘法仅支持 2D,3D+ 会 panic | 限制模型复杂度 |
| D8 | Tanh 导数实现错误(使用 1 - y^2 而非 1 - tanh^2(x)) |
NN 训练收敛异常 |
| D9 | CNN testGeometryCNN 使用随机数据 |
测试无实际意义 |
| D10 | MPU6050 ADDR_0 与 ADDR_1 均为 0x68 |
无法同时使用两个 MPU6050 |
| D11 | @Action 与 @Action_Auto 并存未合并 |
脚本语法冗余 |
相关资源
- Dashun 蜘蛛机器人建模
- 深度分析报告(28 章节,1280 行)
- 仓颉编程语言
- PCA9685 数据手册
- MPU6050 数据手册
许可证
MIT License