🤖 bot4cj 项目深度分析文档
本文档对 bot4cj 项目进行全面、详细的分析,涵盖项目架构、每个模块的实现细节、算法原理、数据流、缺陷与改进建议。目标读者为零基础学习者。
1. 项目总览
1.1 项目是什么
bot4cj 是一个机器人硬件脚本解析器,基于仓颉(Cangjie)编程语言和 Linux I2C 接口。它的核心思想是:
用一种自定义的"矩阵式脚本语言"来描述机器人的硬件构成和动作序列,然后解析并驱动真实硬件执行这些动作。
简单类比:如果把机器人比作一个演员,那么 .mt 脚本就是剧本,bot4cj 就是导演——它读剧本、安排演员(硬件)、指挥表演(执行动作)。
1.2 项目能做什么
1.3 技术栈
| 层级 | 技术 | 用途 |
|---|---|---|
| 应用层 | 仓颉 (Cangjie) | 主程序、解析器、机器人结构、数学库 |
| 系统层 | C/C++ | I2C 驱动、矩阵运算、FFT、CNN、音频 |
| 加速层 | CUDA | GPU 矩阵运算、GPU 激活函数 |
| 脚本层 | .mt 矩阵式脚本 | 硬件定义和动作描述 |
| 前端层 | HTML + Tailwind | Web 管理界面 |
| 工具层 | Python | 图片标注工具、API 测试 |
2. 项目架构与目录结构
bot4cj/
├── src/ # 源代码根目录
│ ├── main.cj # 程序入口:命令行解析、分支选择
│ ├── P.cj # 解析器:MatrixObject、MatrixParser、MatrixSaver
│ ├── r.cj # 机器人结构:RobotStruct、硬件变量类
│ ├── math/ # 数学库
│ │ ├── Matrix.cj # FP32 结构体 + Matrix1 矩阵类(仓颉原生)
│ │ ├── Tensor.cj # 张量类(多维数组)
│ │ ├── nn.cj # 神经网络层 Nn1 + 训练/推理函数
│ │ ├── nns.cj # 多层神经网络训练/推理(旧版,已注释)
│ │ ├── Af.cj # 激活函数枚举
│ │ ├── Ini.cj # 权重初始化:Xavier 正态/均匀
│ │ ├── kalman.cj # 一维卡尔曼滤波器(仓颉实现)
│ │ └── fft.cj # FFT 接口(已注释,改用 C 实现)
│ ├── hd/ # 硬件驱动
│ │ ├── I2C.cj # I2C 通信:直接调用 glibc + 互斥锁系统
│ │ ├── PCA9685.cj # PCA9685 舵机驱动板控制
│ │ ├── MPU6050.cj # MPU6050 陀螺仪/加速度计 + 守护线程
│ │ ├── Servo.cj # 舵机类:角度限制 + 偏移 + 回调
│ │ └── snd.cj # 扬声器类(目前仅延时占位)
│ ├── th/ # 线程与同步
│ │ ├── mutex.cj # pthread 互斥锁封装
│ │ └── pthread.cj # pthread 线程封装
│ ├── cpp/ # C/C++ 共享库源码
│ │ ├── I2C.c # 旧版 I2C 驱动(使用 i2c-smbus)
│ │ ├── Matrix.cpp + .hh # C++ 模板矩阵类 + C 接口封装
│ │ ├── kalman.c + .h # 旧版卡尔曼滤波器(C 实现)
│ │ ├── fft1.c # 基-2 FFT 算法(纯 C)
│ │ ├── fft.cpp + .h # FFT 封装层(C++ → C 接口)
│ │ ├── snd.cpp # 音频播放(Windows WaveAPI / Linux ALSA)
│ │ ├── bot4cj.h # C 头文件:I2C 常量和函数声明
│ │ └── cnn/ # CNN 卷积神经网络
│ ├── cuda/ # CUDA GPU 加速
│ └── py/ # 图片标注工具
├── scripts/ # 动作脚本
├── public/ # Web 前端页面
├── test/ # API 测试
├── Makefile # C/C++ 共享库构建
├── cjpm.toml # 仓颉包管理配置
└── _run.sh / _set.sh # 运行和构建脚本
3. 核心数据流:从脚本到硬件
这是理解整个项目最关键的部分。以下是数据从脚本文件到硬件执行的完整流程:
┌─────────────┐
│ .mt 脚本文件 │ 例如:scripts/test.mt
└──────┬──────┘
│ 文件读取 (InputStream)
▼
┌─────────────┐
│ MatrixParser │ 逐字符解析,输出 MatrixObject 对象
│ (src/P.cj) │ 每个 @name...@ 块变成一个 MatrixObject
└──────┬──────┘
│ LinkedList<MatrixObject>
▼
┌─────────────┐
│ RobotStruct │ 从 MatrixObject 列表构建硬件变量字典
│ (src/r.cj) │ HashMap<String, MatrixVars_Hardware>
└──────┬──────┘
│
├── createAliasVars() 从 @Alias 矩阵创建别名变量
├── createI2CVars() 从 @I2C 矩阵创建 I2C 设备变量
├── createMPU6050Bind() 从 @MPU6050_BIND 矩阵创建陀螺仪变量
├── createPCA9685Vars() 从 @PCA9685 矩阵创建舵机控制板变量
├── createServoVars() 从 @Servo 矩阵创建舵机变量
└── createSpeakerVars() 从 @Speaker 矩阵创建扬声器变量
│
▼
┌─────────────┐
│ active() │ 调用所有硬件变量的 build() 方法(初始化硬件)
└──────┬──────┘
│
▼
┌─────────────┐
│ run() │ 逐行执行 @Action 矩阵中的动作
│ run_drl_ │ 每行解析出各硬件的参数,调用 play() 执行
│ action() │
└──────┬──────┘
│
▼
┌─────────────┐
│ deactive() │ 以倒序调用所有硬件变量的 destroy() 方法
└─────────────┘
关键概念:MatrixVars_Hardware(硬件变量)
这是整个项目的核心抽象。每种硬件(I2C、PCA9685、Servo、Speaker...)都被封装为一个硬件变量,它们:
- 通过闭包持有真实的硬件对象(如
I2C_Orig、PCA9685、Servo) - 通过 JsonValue 进行统一接口通信(输入 JsonValue,输出 JsonValue)
- 有生命周期:
build()初始化,play()执行,destroy()释放
4. 矩阵式脚本语言(.mt)详解
4.1 语法规则
矩阵式脚本是一种声明式、表格型的领域特定语言(DSL),用于描述机器人的硬件构成和动作序列。
基本结构:
@MatrixName ← 矩阵开始,@ 后跟名称
col1 col2 col3; ← 第 0 行:列名声明
val1 val2 val3; ← 第 1 行起:数据行
val4 - val6; ← "-" 表示沿用上一行同列的值
@
- 注释:以
#开头到行末 - 占位符
-:在数据行中,-表示"与上一行同一列的值相同",减少重复书写。
4.2 各矩阵对象的含义
| 矩阵名 | 用途 | 关键列 |
|---|---|---|
@Alias | 定义参数别名 | name, alias |
@I2C | 定义 I2C 总线设备 | name, path |
@PCA9685 | 定义舵机控制板 | name, I2C, addr |
@MPU6050_BIND | 定义陀螺仪 | name, I2C, addr |
@Speaker | 定义扬声器 | name, channels, sample_rate, volumn, max_f, min_f |
@Servo | 定义舵机 | name, max, min, offset, controller, channel |
@Action | 定义动作序列 | 格式为 硬件名.参数名 |
4.3 @Action 矩阵详解
@Action 是最核心的矩阵,它定义了机器人的动作序列:
@Action
s1.A s2.A s3.A ... spk.F spk.delay; ← 列名:硬件变量.参数名
45 - 45 ... 10 200; ← 第1行:站立姿态
90 - - ... - 20; ← 第2行:左后方抬起
...
@
4.4 蜘蛛机器人动作示例解读
以 scripts/test.mt 为例,这是一个 8 足蜘蛛机器人的行走步态:
@Action
s1.A s2.A s3.A s4.A s5.A s6.A s7.A s8.A s9.A s10.A spk.F spk.delay;
45 - 45 - 45 - 45 - 90 90 10 200; # 站立
90 - - - - - - - - - - 20; # 左后方抬起
45 - - - - - - - - - 0 500; # 恢复站立
- - 90 - - - 45 - - - - 20; # 右后方抬起
...
@
- s1-s8 是 8 个舵机(4 条腿,每腿 2 个关节)
- s9-s10 是云台舵机
- spk.F 是扬声器频率,spk.delay 是延时
5. 解析器模块详解
5.1 MatrixObject 类
用途:表示解析后的一个矩阵对象,对应脚本中 @name ... @ 之间的内容。
MatrixObject {
name: String ← 矩阵名称
values: ArrayList<ArrayList<String>> ← 二维字符串矩阵
}
| 方法 | 功能 |
|---|---|
hasName() | 是否已命名 |
[](row, col) | 像数组一样用下标访问 |
indexOfCol(row, key) | 在某行中查找列号 |
addRune(c) | 添加字符到缓冲区 |
submitName() | 提交名字 |
submitItem() | 提交元素 |
submitLine(count) | 提交一行,检查列数一致性 |
save(output) | 将矩阵对象写回文件流 |
5.2 MatrixParser 类
用途:将输入流逐字符解析为 MatrixObject 对象。
算法:有限状态机(FSM)
| 标志 | 含义 |
|---|---|
flag | 是否遇到结束的 @ |
nl | 是否处于新行起始位置 |
cm | 是否处于注释中 |
nm | 是否正在解析名称行(@ 后的第一行) |
输入字符 c
├── 如果在注释中 (cm=true)
│ ├── c == '\n' → 注释结束,nl=true, cm=false
│ └── 其他 → 忽略
├── 如果在新行起始 (nl=true)
│ ├── c 是空白 → 维持现状
│ ├── c == '\n' → 空行,行号+1
│ ├── c == '@' 且未命名 → 开始名称行,nm=true
│ ├── c == '@' 且已命名 → 结束标志,flag=true
│ └── 其他 → 内容字符,加入缓冲区
├── 如果不在新行 (nl=false)
│ ├── 在名称行且遇空白 → 提交名字
│ ├── 遇空白/制表符 → 提交当前元素
│ ├── c == ';' → 提交元素并提交行
│ └── 其他 → 加入缓冲区
5.4 异常体系
| 异常类 | 含义 |
|---|---|
ParseExcept | 解析异常基类 |
BufOverTheLine | 缓冲区过长 |
DoesNotSync | 矩阵行没对齐(列数不一致) |
UnknowExcept | 未知异常兜底 |
6. 机器人结构模块详解
6.1 MatrixVars_Hardware 基类
这是整个硬件抽象的核心。
MatrixVars_Hardware(基类)
├── things: (JsonValue) → JsonValue ← 事件回调(核心!)
├── rise: Option<() → Unit> ← 初始化回调
├── free: Option<() → Unit> ← 释放回调
├── play(input) → things(input) ← 执行动作
├── build() → rise() ← 初始化硬件
└── destroy() → free() ← 释放硬件
为什么用 JsonValue 通信?不同硬件需要不同参数:
- PCA9685 需要
{"channel": 0, "angle": 90.0} - I2C 需要
{"mode": "set_addr", "addr": 0x40} - Servo 需要
{"angle": 180.0} - Speaker 需要
{"frequency": 1000.0, "delay": 400}
6.2 各硬件变量类
MtVars_I2C(I2C 变量)
things 支持 4 种模式:
get_fd:获取文件描述符set_addr:设置从机地址set_val:写寄存器get_val:读寄存器
MtVars_Servo(舵机变量)
Servo.setAngle() 逻辑:
角度 = 输入角度 + 偏移值(offset)
如果 角度 > 最大值(max) → 角度 = max
如果 角度 < 最小值(min) → 角度 = min
调用回调函数设置角度
6.3 RobotStruct 类
RobotStruct(input)
├── readMatrix(input) 解析所有矩阵对象
└── createHardVars() 创建硬件变量字典
├── createAliasVars()
├── createI2CVars()
├── createMPU6050Bind()
├── createPCA9685Vars()
├── createServoVars()
└── createSpeakerVars()
active() 初始化所有硬件
run() → run_drl_action() 执行动作
deactive() 倒序释放所有硬件
7. 硬件驱动层详解
7.1 I2C 通信
项目直接在仓颉中通过 foreign func 声明并调用 Linux glibc 的原生函数:
foreign func open(path: CString, flag: Int32, ...): Int32
foreign func close(fd: Int32): Int32
foreign func ioctl(fd: Int32, addr: UInt64, ...): Int32
foreign func read(fd: Int32, buf: CPointer<Unit>, count: UIntNative): IntNative
foreign func write(fd: Int32, buf: CPointer<Unit>, count: UIntNative): IntNative
7.2 I2C 互斥锁系统
MAIN_LOCK (主锁) ← 保护 LOCKS 数组的操作
└── LOCKS[0..19] (锁具数组) ← 每个 I2C 设备一个锁
└── I2C_Lock {
i2c_fd: Int32 ← 绑定的 I2C 设备文件句柄
lock: CPointer ← pthread_mutex_t 指针
is_active: Bool ← 是否激活
}
7.3 PCA9685 舵机控制板
角度转 PWM:
脉宽 = 0.5 + (2.5 - 0.5) * (angle / 180.0) ← 0°→0.5ms, 180°→2.5ms
OFF值 = 脉宽 * 4096 / 20 ← 20ms 周期, 12位分辨率
setPWM(channel, ON=0, OFF=计算值)
7.4 MPU6050 陀螺仪/加速度计
守护线程 mpu6050_main():
- 读取原始传感器数据
- 对 6 个轴分别进行卡尔曼滤波
- 打印滤波后的数据
- 睡眠 10ms
7.6 Spk 扬声器类
当前状态:仅实现了延时功能,实际发声被注释掉。C++ 实现的音频播放(src/cpp/snd.cpp)是完整的,支持 Windows WaveAPI 和 Linux ALSA。
8. 数学库详解
8.2 Matrix1 矩阵类
数据布局:一维数组 Array<FP32>,行优先存储。
arr[row * col + col] ← 元素访问公式
| 运算 | 符号 | 含义 | 形状要求 |
|---|---|---|---|
| 矩阵加法 | A + B | 逐元素相加 | 同形状 |
| 广播加法 | A + s | 每个元素加标量 | - |
| 矩阵减法 | A - B | 逐元素相减 | 同形状 |
| 逐元素乘 | A * B | 逐元素相乘(Hadamard积) | 同形状 |
| 矩阵乘法 | A.dot(B) | 矩阵点积(MatMul) | A.col == B.row |
| 转置 | A.T() | 行列互换 | - |
矩阵乘法算法(dot):
对于结果矩阵的每个元素 (i, j):
sum = 0
对于 k in 0..A.col:
sum += A[i, k] * B[k, j]
结果[i, j] = sum
时间复杂度:O(m × n × k)
9. 神经网络模块详解
9.1 Nn1 全连接层
class Nn1 {
inputno: Int64 ← 输入维度
outputno: Int64 ← 输出维度
weights: Matrix1 ← 权重矩阵 (inputno, outputno)
bias: Matrix1 ← 偏置向量 (1, outputno)
learning_rate: FP32 ← 学习率
f: Af ← 激活函数
}
forward() 前向传播: a = f(Wx + b)
backward() 反向传播:
δ = errs * f'(z) ← 误差 × 激活函数导数
weights_grad = x^T · δ ← 权重梯度
bias_grad = δ ← 偏置梯度
errs_up = δ · W^T ← 传给上一层的误差
9.2 激活函数
| 函数 | 公式 | 导数 | 用途 |
|---|---|---|---|
| Sigmoid | f(x) = 1/(1+e^(-x)) | f'(x) = f(x)(1-f(x)) | 二分类输出层 |
| ReLU | f(x) = max(0, x) | f'(x) = 1 if x>0, else 0 | 隐藏层 |
| Leaky_ReLU | f(x) = x if x>0, else αx | f'(x) = 1 if x>0, else α | 隐藏层 |
| Tanh | f(x) = tanh(x) | f'(x) = 1 - tanh²(x) | 隐藏层 |
| Softmax | f(x_i) = e^(x_i) / Σe^(x_j) | 雅可比矩阵 | 多分类输出层 |
9.3 Xavier 权重初始化
σ = sqrt(2 / (fan_in + fan_out)) ← Xavier 正态
limit = sqrt(6 / (fan_in + fan_out)) ← Xavier 均匀(Glorot)
10. 卡尔曼滤波详解
卡尔曼滤波是一种最优估计算法,用于从含有噪声的测量数据中估计系统的真实状态。
一维卡尔曼滤波器 5 个核心公式
| 步骤 | 公式 | 含义 |
|---|---|---|
| 预测状态 | X_mid = A · X_last | 根据上一次最优估计预测当前状态 |
| 预测协方差 | P_mid = A · P_last + Q | 预测的不确定性增大(+系统噪声Q) |
| 计算卡尔曼增益 | kg = P_mid / (P_mid + R) | 测量越可靠(R小),增益越大 |
| 更新状态 | X_now = X_mid + kg · (dat - X_mid) | 用测量值修正预测值 |
| 更新协方差 | P_now = (1 - kg) · P_mid | 估计的不确定性减小 |
11. FFT 快速傅里叶变换详解
快速傅里叶变换(FFT)是一种高效计算离散傅里叶变换(DFT)的算法。将时域信号转换为频域表示。
DFT 公式: X[k] = Σ x[n] · e^(-j·2π·k·n/N)
算法:Cooley-Tukey 基-2 FFT —— 将 N 点 DFT 分解为两个 N/2 点 DFT,递归分解,时间复杂度从 O(N²) 降低到 O(N·log N)。
蝶形运算
对于每一级 l:
对于每一组 j:
对于每个蝶形 k:
t = A[jl1k] · W[ij] ← 旋转因子乘法
A[jl1k] = A[jl0k] - t ← 蝶形运算上支
A[jl0k] = A[jl0k] + t ← 蝶形运算下支
12. CNN 卷积神经网络详解
12.1 CNN 架构
CNN 模块完全用 C++ 实现,通过 C 接口(extern "C")暴露给仓颉调用。
| 层 | 文件 | 功能 |
|---|---|---|
| ConvLayer | conv.cpp/h | 2D 卷积层 + 反向传播 + 参数更新 |
| PoolingLayer | pooling.cpp/h | 最大/平均池化 |
| GlobalAveragePooling | ga_pooling.cpp/h | 全局平均池化 |
| FlattenLayer | flatten.cpp/h | 展平(4D → 2D) |
| ImageLoader | imgl.cpp/h | 图像加载 + 归一化 |
卷积层前向传播
对于每个输出通道 oc:
对于每个空间位置 (oh, ow):
sum = bias[oc]
对于每个输入通道 ic:
对于每个核位置 (kh, kw):
sum += weight[oc,ic,kh,kw] * input[ic,oh*stride+kh,ow*stride+kw]
output[oc,oh,ow] = sum
13. CUDA GPU 加速详解
13.1 CUDA 矩阵运算
__global__ void _devAdd(float* d1, float* d2, float* r, int64_t n) {
int i = blockIdx.x * blockDim.x + threadIdx.x; ← 计算全局线程ID
if (i < n) {
r[i] = d1[i] + d2[i]; ← 每个线程处理一个元素
}
}
| 函数 | 功能 |
|---|---|
Cu4cj_Orig(n) | 在 GPU 上分配 n 个 float 的内存 |
Cu4cj_Zero(n) | 在 GPU 上分配并清零 |
Cu4cj_ToDev(h, n) | 主机 → 设备拷贝 |
Cu4cj_ToHost(d, h, n) | 设备 → 主机拷贝 |
Cu4cj_Free(d) | 释放 GPU 内存 |
14. 线程与同步模块详解
直接封装 pthread 互斥锁和线程:
foreign func pthread_mutex_init(mutex, attr): Int32
foreign func pthread_mutex_destroy(mutex): Int32
foreign func pthread_mutex_lock(mutex): Int32
foreign func pthread_mutex_unlock(mutex): Int32
public class Pth {
init(_main, args) → pthread_create(...) ← 创建线程
join(retval) → pthread_join(...) ← 等待线程结束
close() → pthread_cancel(...) ← 取消线程
}
15. HTTP 服务器模块详解
| 路径 | 方法 | 功能 |
|---|---|---|
/api/v2/bot_run | POST | 接收动作脚本并执行 |
/ | GET | 返回前端页面 |
/api/v1/fs | POST | 文件系统操作(列表目录) |
16. 辅助工具详解
- 图片标注工具(
src/py/labeled.py):Python + Tkinter + PIL + OpenCV,用于 CNN 训练数据标注 - 前端页面(
public/index.html):科技感展示页面,Tailwind CSS,暗色模式 - API 测试(
test/test_api_fs.py):测试文件系统 API
17. 构建系统详解
| 目标 | 源文件 | 输出 | 用途 |
|---|---|---|---|
libi2c4cj.so | I2C.c | I2C 驱动 | 旧版(已弃用) |
libsnd4cj.so | snd.cpp | 音频播放 | WaveAPI / ALSA |
libmt4cj.so | Matrix.cpp / matrix.cu | 矩阵运算 | CPU 或 GPU 版本 |
libfft4cj.so | fft1.c + fft.cpp | FFT | 快速傅里叶变换 |
libcnn4cj.so | cnn_i.cpp + ... | CNN | 卷积神经网络 |
18. 全局缺陷与改进建议
18.1 严重缺陷
| 编号 | 缺陷 | 位置 | 详细说明 | 严重程度 |
|---|---|---|---|---|
| D1 | 析构器调用时间不确定 | r.cj:28 | 仓颉的 GC 不保证析构器调用时间,I2C 文件描述符可能泄漏 | 高 |
| D2 | 扬声器仅延时未发声 | hd/snd.cj:17 | play() 只 sleep,C++ 实现的 play_frequency() 未被调用 |
高 |
| D3 | MPU6050 线程无法安全退出 | hd/MPU6050.cj:115 | mpu6050_main() 是无限循环,pthread_cancel 可能在不安全点中断 |
高 |
| D4 | I2C 锁系统线性扫描 | hd/I2C.cj:129 | 每次加锁/解锁都遍历 20 个元素的数组,O(n) 复杂度 | 中 |
| D5 | xavierUniformInit 每个元素新建 Random | math/Ini.cj:30 | 循环内每次 DateTime.now().nanosecond + Random(),种子可能重复 |
中 |
| D6 | Softmax 雅可比矩阵反向传播未正确使用 | math/Af.cj:246 | softmax_jacobian 返回 n×n 矩阵,但 backward 调用者期望与输入同形状 |
高 |
| D8 | tanh 导数输入错误 | math/Af.cj:194-206 | 计算 1 - x*x 用的是原始输入 x,应改为 1 - y*y |
高 |
| D9 | I2C 读寄存器返回 Int8 而非 UInt8 | hd/I2C.cj:81 | 负值寄存器数据会出错 | 中 |
| D10 | MPU6050 ADDR_0 和 ADDR_1 相同 | hd/MPU6050.cj:14-15 | 两个地址常量都是 0x68,ADDR_1 应为 0x69 | 中 |
18.2 设计缺陷
| 编号 | 缺陷 | 详细说明 | 建议 |
|---|---|---|---|
| D12 | JsonValue 通信开销大 | 每次硬件操作都要构造/解析 JSON | 对高频路径提供直接调用接口 |
| D13 | 硬件变量创建顺序硬编码 | createHardVars() 中顺序固定 | 使用依赖图自动排序 |
| D14 | 无 batch 训练支持 | 神经网络每次只训练一个样本 | 增加 batch 维度 |
| D15 | 无 Adam 优化器 | 仓颉版 Nn1 只有 SGD | 实现 Adam 优化器 |
| D20 | 无单元测试 | 数学库、解析器等无自动化测试 | 添加测试框架 |
18.3 安全缺陷
| 编号 | 缺陷 | 详细说明 |
|---|---|---|
| D21 | 文件系统 API 无认证 | /api/v1/fs 可列出任意目录内容 |
| D22 | HTTP 服务器无认证 | /api/v2/bot_run 可执行任意脚本 |
| D23 | 路径遍历风险 | 文件系统 API 接受用户输入的路径 |
19. 学习路线图
阅读
scripts/test.mt,理解 .mt 语法,手动写一个简单脚本从 MatrixObject 开始,跟踪 MatrixParser 的状态机逻辑
学习 I2C 通信原理,阅读 PCA9685、MPU6050 驱动代码
理解闭包设计,跟踪硬件变量创建和 run_drl_action() 流程
学习矩阵运算、激活函数,手动计算前向/反向传播
卡尔曼滤波、FFT 蝶形运算、CNN、CUDA GPU 编程
附录 A:仓颉语言关键语法速查
| 语法 | 含义 | 对应语言 |
|---|---|---|
package foo | 声明包 | Java package |
import std.io.* | 导入 | Java import |
class A <: B | 继承 | Java extends |
open class | 允许继承 | Java 非 final |
let / var | 不可变/可变 | Kotlin val/var |
Option<T> | 可选类型 | Java Optional |
Some(v) / None | 有值/无值 | Optional.of/present |
if (let Some(v) <- expr) | if-let 解构 | Swift if-let |
match(expr) { case ... } | 模式匹配 | Kotlin when / Rust match |
foreign func | FFI 声明 | Java native / Rust extern |
unsafe { } | 不安全块 | Rust unsafe |
CPointer<T> | C 指针 | Rust *mut T |
@C | C 兼容注解 | 使结构体内存布局兼容 C |
operator func [] | 运算符重载 | C++ operator[] |
extend A { } | 扩展方法 | Kotlin extension |
附录 B:术语表
| 术语 | 英文 | 含义 |
|---|---|---|
| 舵机 | Servo | 一种可以精确控制角度的电机 |
| I2C | Inter-Integrated Circuit | 一种两线制串行总线协议 |
| PWM | Pulse Width Modulation | 脉宽调制,通过改变脉冲宽度控制输出 |
| 陀螺仪 | Gyroscope | 测量角速度的传感器 |
| 前向传播 | Forward Propagation | 神经网络从输入到输出的计算过程 |
| 反向传播 | Backpropagation | 神经网络从输出到输入的梯度计算过程 |
| 梯度下降 | Gradient Descent | 沿梯度反方向更新参数以最小化损失 |
| 学习率 | Learning Rate | 每次参数更新的步长 |
| 激活函数 | Activation Function | 引入非线性的函数(如 ReLU、Sigmoid) |
| 卡尔曼增益 | Kalman Gain | 决定多大程度上相信测量值 vs 预测值 |
| 傅里叶变换 | Fourier Transform | 将信号从时域转换到频域 |
| 蝶形运算 | Butterfly Operation | FFT 中的基本计算单元 |
| 卷积 | Convolution | 滑动窗口加权求和的运算 |
| 池化 | Pooling | 降采样操作(取最大值或平均值) |
| FFI | Foreign Function Interface | 调用其他语言函数的接口 |
| DRL | Deep Reinforcement Learning | 深度强化学习 |