Compare commits

..

17 Commits

Author SHA1 Message Date
spdis 3f96df39d4 Revert: 移除CLAHE预处理(模型反光加剧) 2026-07-07 18:20:46 +08:00
spdis 0502948bcd speed20: raw_frame CLAHE预处理(搜线+模型共享,clipLimit=1.5) 2026-07-07 18:06:17 +08:00
spdis cbb54b4882 speed20: Otsu全局阈值改为自适应局部阈值(11x11 Gaussian) 2026-07-07 17:52:01 +08:00
spdis 66fb213861 chore: 工具链搬至~/loongson-*, OpenCV搬至D盘 2026-07-07 15:04:10 +08:00
spdis 97e06314cc speed20: 搜线强化(GaussianBlur5x5+形态学7x7) 2026-07-06 19:00:10 +08:00
spdis ad48c955d9 speed20: 搜线反光优化(高斯模糊+形态学核5x5) 2026-07-06 18:49:03 +08:00
spdis b69a5ff5bc speed20: V通道反光剔除(高亮+低饱和像素标记为非赛道) 2026-07-06 18:35:46 +08:00
spdis a43ff769d4 speed20: 平滑线性转向消除死区断崖 2026-07-06 17:25:24 +08:00
spdis afc839e8cb speed20: Z_COOLDOWN基础速度16+保留原有降速13 2026-07-06 17:21:33 +08:00
spdis 08b00d6c97 speed20: boost固定26 + Z_COOLDOWN定速16 2026-07-06 17:19:17 +08:00
spdis b9141eaf8a fix1: boost恢复为1.6x乘法 2026-07-06 17:13:02 +08:00
spdis e720009794 fix: boost改为固定26 + 删除死代码
- motor_update: boost从乘法改为固定值26
- 删除废弃的font_bitmap.h中文渲染代码(已改用PNG)
- 移除无源码的lcd_test编译目标
- 设备speed=20
2026-07-06 17:11:15 +08:00
spdis 8ee66fe444 {固化}16速45秒两圈 2026-07-06 17:02:10 +08:00
spdis 7b220f5c3b docs: 更新ARCHITECTURE.md参数表与行为文档
- 模型: Mild v12->v13, 阈值更新为{0.80,0.70,0.80,0.85}
- 新增 foresee_lost_scale / sharp_turn_scale 参数
- 移除已删除的 zebra_detect.cpp 引用
- 新增 zebra 冷却期控制策略表(foresee/bang-bang/降速)
- 新增 pedestrian_stop.png LCD 图片显示说明
- 新增模型转换工具 tools/ 引用
2026-07-06 16:56:16 +08:00
spdis 7284a8d037 chore: 删除废弃的zebra_detect(斑马线检测已由Mild模型替代) 2026-07-04 21:17:34 +08:00
spdis 54f13984a9 chore: 从git跟踪中移除.vscode目录(.gitignore) 2026-07-04 21:15:46 +08:00
spdis 670f84131b feat: 添加模型转换工具(Mild v13 PyTorch->bin导出)
- tools/export_mild_v13.py: PyTorch .pth -> 自定义 .bin 导出脚本
- tools/inspect_pth.py: 检查 .pth 权重文件结构
- tools/best_v13_mild_r2.pth: 训练好的 PyTorch 权重
- .gitignore: 追加 build 变体目录和生成文件
2026-07-04 21:15:10 +08:00
21 changed files with 1586 additions and 1751 deletions
+9 -5
View File
@@ -1,14 +1,18 @@
.vscode/* .vscode/
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace *.code-workspace
build/* build/*
build2/* build2/*
build3/* build3/*
build4/*
build_lsx/*
build_new/*
test/ test/
ZebraCrossing_Detection-master/
ZebraCrossing_Detection-master.zip
smartcar2_code.txt
smartcar_test
# Local History for Visual Studio Code # Local History for Visual Studio Code
.history/ .history/
-4
View File
@@ -1,4 +0,0 @@
{
"python-envs.defaultEnvManager": "ms-python.python:conda",
"python-envs.defaultPackageManager": "ms-python.python:conda"
}
+1 -1
View File
@@ -14,7 +14,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wall")
project(smartcar_demo2 VERSION 0.1.0 LANGUAGES C CXX) project(smartcar_demo2 VERSION 0.1.0 LANGUAGES C CXX)
# OpenCV 设备端路径 # OpenCV 设备端路径
set(OpenCV_DIR /home/spdis/loongson/opencv-4.13.0/loongson/lib/cmake/opencv4) set(OpenCV_DIR /mnt/D/PPPProgram/smartcar/opencv-4.13.0/loongson/lib/cmake/opencv4)
find_package(OpenCV REQUIRED) find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS}) include_directories(${OpenCV_INCLUDE_DIRS})
message(STATUS "OpenCV Include Directories: ${OpenCV_INCLUDE_DIRS}") message(STATUS "OpenCV Include Directories: ${OpenCV_INCLUDE_DIRS}")
+1 -1
View File
@@ -5,7 +5,7 @@ SET(CROSS_COMPILE 1)
IF(CROSS_COMPILE) IF(CROSS_COMPILE)
SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR loongson) set(CMAKE_SYSTEM_PROCESSOR loongson)
SET(TOOLCHAIN_DIR "/opt/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.6") SET(TOOLCHAIN_DIR "/home/spdis/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.6")
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-linux-gnu-g++) set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-linux-gnu-g++)
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-linux-gnu-gcc) set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-linux-gnu-gcc)
+21 -8
View File
@@ -247,9 +247,20 @@ ZNORMAL 期间:
└──────────┘ └──────────┘
NORMAL: 允许通行,检测斑马线 NORMAL: 允许通行,检测斑马线
STOP: 刹停 4 秒,g_zstate==Z_STOP 传给 motor_update → 编码器刹车 STOP: 刹停 3 秒,g_zstate==Z_STOP 传给 motor_update → 编码器刹车
LCD 显示 pedestrian_stop.png(不受 showImg 控制),进入/退出时清屏
COOLDOWN: 恢复行驶但斑马线状态机停止检测 5 秒(防止重复触发) COOLDOWN: 恢复行驶但斑马线状态机停止检测 5 秒(防止重复触发)
仅跳过检测,不影响其他功能(舵机/巡线正常) 仅跳过检测,不影响其他功能(舵机/巡线正常)
### 斑马线冷却期控制策略 (Z_COOLDOWN)
| 时间窗口 | 控制 | 说明 |
|----------|------|------|
| 0~2s | 全速起步 | boost 1.5x 速度持续 0.7s |
| 2~5s | foresee=24 | 缩短前瞻走稳 |
| 3.3~5s | 降速上限 13 + bang-bang 打满 | 一次机会:偏差出现→方向锁定打满→方向翻转/回正即退出 |
**bang-bang 逻辑**`steering_update()`):Z_COOLDOWN 3.3~5s 内,偏差超出死区后锁定方向一次性打满(左满 1.2ms / 右满 1.8ms),直到偏差方向翻转或回到死区退出,后续走正常线性转向。
``` ```
**关键变量:** **关键变量:**
@@ -356,12 +367,14 @@ lcd_render():
| `./start` | int(0/1) | 0 | 0 | 使能开关,1=电机运行 | | `./start` | int(0/1) | 0 | 0 | 使能开关,1=电机运行 |
| `./debug` | int(0/1) | 0 | (不写入) | 每30帧重载配置+允许存图 | | `./debug` | int(0/1) | 0 | (不写入) | 每30帧重载配置+允许存图 |
| `./showImg` | int(0/1) | 0 | (不写入) | LCD 显示(每10帧轮询→g_lcd_on | | `./showImg` | int(0/1) | 0 | (不写入) | LCD 显示(每10帧轮询→g_lcd_on |
| `./foresee` | double | 80 | 40 | 舵机前瞻行 (显示空间像素) | | `./foresee` | double | 80 | 40 | 舵机前瞻行 (显示空间像素, Z_COOLDOWN 2~5s 内缩短为 24) |
| `./foresee_lost_scale` | double | 0.7 | 0.7 | 丢线时前瞻缩放 (<1=看更远) |
| `./sharp_turn_scale` | double | 0.5 | 0.5 | 急弯时前瞻缩放 (<1=看更远) |
| `./deadband` | double | 5 | 8 | 舵机死区 (显示空间像素) | | `./deadband` | double | 5 | 8 | 舵机死区 (显示空间像素) |
| `./steer_gain` | double | 1.0 | 1.5 | 舵机增益 | | `./steer_gain` | double | 1.0 | 1.5 | 舵机增益 |
| `./center_bias` | double | 0 | (不写入) | 中线偏置修正 | | `./center_bias` | double | 0 | (不写入) | 中线偏置修正 |
| `./zebrasee` | double | 60 | (不写入) | 斑马线近界阈值 (模型空间cy) | | `./zebrasee` | double | 60 | (不写入) | 斑马线近界阈值 (模型空间cy) |
| `./destfps` | double | 30* | (不写入) | 目标帧率 (*代码兜底值) | | `./destfps` | double | - | (不写入) | 目标帧率 |
| `./saveImg` | int(0/1) | - | (不写入) | 保存帧图像 (需 debug=1) | | `./saveImg` | int(0/1) | - | (不写入) | 保存帧图像 (需 debug=1) |
| `./cone_avoid_gain` | double | 0.3 | 0.3 | 锥桶中线变形推离量 (归一化) | | `./cone_avoid_gain` | double | 0.3 | 0.3 | 锥桶中线变形推离量 (归一化) |
| `./cone_avoid_range` | int | 30 | 30 | 变形斜坡陡峭度 | | `./cone_avoid_range` | int | 30 | 30 | 变形斜坡陡峭度 |
@@ -402,7 +415,6 @@ lcd_render():
| 文件 | 功能 | 排除原因 | | 文件 | 功能 | 排除原因 |
|---|---|---| |---|---|---|
| `zebra_detect.cpp` | 经典斑马线检测 | 已被 Mild 模型替代 |
| `PIDController.cpp` | 位置式/增量式 PID | 电机开环直驱,无调用点 | | `PIDController.cpp` | 位置式/增量式 PID | 电机开环直驱,无调用点 |
| `serial.cpp` | VOFA 串口可视化 | 未使用 | | `serial.cpp` | VOFA 串口可视化 | 未使用 |
@@ -412,15 +424,16 @@ lcd_render():
--- ---
## 模型:Mild v12 ## 模型:Mild v13
- **推理引擎**`src/model_v10.{hpp,cpp}`(名称为兼容保留,内部为 Mild v3) - **推理引擎**`src/model_v10.{hpp,cpp}`(名称为兼容保留,内部为 Mild Mega r2 v3
- **输入**160×120 BGR - **输入**160×120 BGR
- **输出**:4 类 + 背景 → 9 通道:0=锥桶, 1=红灯, 2=绿灯, 3=斑马线 - **输出**:4 类 + 背景 → 9 通道:0=锥桶, 1=红灯, 2=绿灯, 3=斑马线
- **架构**3→9→9→13→13→19→19→19→44→44→64→64 → head(64→64,dw) → out(64→9) - **架构**3→9→9→13→13→19→19→19→44→44→64→64 → head(64→64,dw) → out(64→9)
- **阈值**`{0.65, 0.75, 0.80, 0.82}`(锥桶/红灯/绿灯/斑马线) - **阈值**`{0.80, 0.70, 0.80, 0.85}`(锥桶/红灯/绿灯/斑马线)
- **权重文件**`mild_v12.bin`105KB 自定义二进制格式) - **权重文件**`mild_v12.bin`103KB 自定义二进制格式,实际模型为 Mild v13,沿用旧名
- **推理频率**:每 2 帧一次(跳帧节省 CPU) - **推理频率**:每 2 帧一次(跳帧节省 CPU)
- **转换工具**`tools/export_mild_v13.py`PyTorch .pth → .bin
--- ---
+72
View File
@@ -0,0 +1,72 @@
# 比赛参数固化
> 截至 2026-07-0416速,45秒两圈
## 设备实际配置文件 (`/home/root/smartcar2/`)
```bash
speed=16 # 目标速度 (% 占空比)
deadband=8 # 舵机死区 (显示空间像素)
steer_gain=1.5 # 舵机增益
foresee=40 # 舵机前瞻行 (显示空间像素)
foresee_lost_scale=0.6# 丢线时前瞻缩放
sharp_turn_scale=0.5 # 急弯前瞻缩放
zebrasee=18 # 斑马线近界阈值 (模型空间 cy)
curve_slope=0.2 # 弯道减速斜率
curve_min=0.8 # 弯道最低速度倍率
cone_avoid_gain=0.3 # 锥桶推离力度
cone_avoid_range=30 # 锥桶斜坡陡峭度
cone_speed=0.5 # 锥桶速度倍率 (当前未生效)
cone_min_frames=3 # 锥桶确认帧数
cone_margin=0 # 0=中心点, 1=框边缘
cone_thresh=0.80 # 锥桶置信度阈值
cone_hold_frames=30 # 锥桶消失后保持帧数
brake_scale=10 # 刹车速度→占空比系数
brake_max=10000 # 最大刹车占空比 (ns)
lidar_enable=1 # 激光避障 (代码中已禁用)
start=1 # 电机使能运行中
debug=1 # 热调参模式 (每30帧重载配置)
showImg=0 # LCD 预览关闭
```
## 代码硬编码行为
### 斑马线状态机
- **进入 Z_STOP**: 播报语音 + LCD 显示 `pedestrian_stop.png`
- **停车**: 3 秒编码器刹车
- **冷却 Z_COOLDOWN**: 5 秒内不检测斑马线
### 斑马线冷却期控制 (Z_COOLDOWN)
| 时间 | 控制 |
|------|------|
| 0~0.7s | boost 1.5x 起步 |
| 2~5s | foresee 缩短为 24 |
| 3.3~5s | 降速上限 13 + 方向锁定一次性打满 |
### 斑马线冷却期 bang-bang 转向
- 3.3~5 秒内部署
- 偏差超出死区后锁定方向一次性打满
- 方向翻转或回到死区即退出,机会用完
- 退出后走正常线性转向
### 模型
- **Mild v13** (文件名为 `mild_v12.bin`)
- 输入 160×120 BGR,输出 4 类:锥桶/红灯/绿灯/斑马线
- 阈值:`{0.80, 0.70, 0.80, 0.85}`
- 推理频率:每 2 帧一次
### 硬件
- **LCD**: 160×128 RGB565
- **摄像头**: 640×480 MJPEG → 1/4 解码 160×120
- **舵机**: pwmchip1/pwm0, 3ms 周期, 1.2~1.8ms 量程
- **电机**: pwmchip8/pwm1+2, 20kHz, 开环占空比
- **编码器**: GPIO67 脉冲, GPIO72 方向, 100ms 窗口测速
- **语音**: I2C-2 地址 0x34
### 编译
```bash
cd smartcar2 && mkdir -p build && cd build
cmake .. && make -j$(nproc)
```
- 工具链: `/opt/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.6`
- OpenCV: 4.13.0 (交叉编译, 仅 core/imgproc/imgcodecs/videoio)
+107 -107
View File
@@ -1,107 +1,107 @@
#ifndef GLOBAL_H #ifndef GLOBAL_H
#define GLOBAL_H #define GLOBAL_H
#include <string> #include <string>
// ── 参数文件名 ── // ── 参数文件名 ──
const std::string kp_file = "./kp"; const std::string kp_file = "./kp";
const std::string ki_file = "./ki"; const std::string ki_file = "./ki";
const std::string kd_file = "./kd"; const std::string kd_file = "./kd";
const std::string start_file = "./start"; const std::string start_file = "./start";
const std::string showImg_file = "./showImg"; const std::string showImg_file = "./showImg";
const std::string destfps_file = "./destfps"; const std::string destfps_file = "./destfps";
const std::string foresee_file = "./foresee"; const std::string foresee_file = "./foresee";
const std::string foresee_lost_scale_file = "./foresee_lost_scale"; const std::string foresee_lost_scale_file = "./foresee_lost_scale";
const std::string sharp_turn_scale_file = "./sharp_turn_scale"; const std::string sharp_turn_scale_file = "./sharp_turn_scale";
const std::string zebrasee_file = "./zebrasee"; const std::string zebrasee_file = "./zebrasee";
const std::string saveImg_file = "./saveImg"; const std::string saveImg_file = "./saveImg";
const std::string speed_file = "./speed"; const std::string speed_file = "./speed";
const std::string deadband_file = "./deadband"; const std::string deadband_file = "./deadband";
const std::string steer_gain_file = "./steer_gain"; const std::string steer_gain_file = "./steer_gain";
const std::string center_bias_file = "./center_bias"; const std::string center_bias_file = "./center_bias";
const std::string debug_file = "./debug"; const std::string debug_file = "./debug";
const std::string cone_avoid_gain_file = "./cone_avoid_gain"; const std::string cone_avoid_gain_file = "./cone_avoid_gain";
const std::string cone_avoid_range_file = "./cone_avoid_range"; const std::string cone_avoid_range_file = "./cone_avoid_range";
const std::string cone_speed_file = "./cone_speed"; const std::string cone_speed_file = "./cone_speed";
const std::string cone_min_frames_file = "./cone_min_frames"; const std::string cone_min_frames_file = "./cone_min_frames";
const std::string cone_margin_file = "./cone_margin"; const std::string cone_margin_file = "./cone_margin";
const std::string cone_thresh_file = "./cone_thresh"; const std::string cone_thresh_file = "./cone_thresh";
const std::string cone_hold_frames_file = "./cone_hold_frames"; const std::string cone_hold_frames_file = "./cone_hold_frames";
const std::string cone_return_gain_file = "./cone_return_gain"; const std::string cone_return_gain_file = "./cone_return_gain";
const std::string cone_return_frames_file = "./cone_return_frames"; const std::string cone_return_frames_file = "./cone_return_frames";
const std::string brake_scale_file = "./brake_scale"; const std::string brake_scale_file = "./brake_scale";
const std::string brake_max_file = "./brake_max"; const std::string brake_max_file = "./brake_max";
const std::string curve_slope_file = "./curve_slope"; const std::string curve_slope_file = "./curve_slope";
const std::string curve_min_file = "./curve_min"; const std::string curve_min_file = "./curve_min";
const std::string lidar_thresh_file = "./lidar_thresh"; const std::string lidar_thresh_file = "./lidar_thresh";
const std::string lidar_pre_file = "./lidar_pre"; const std::string lidar_pre_file = "./lidar_pre";
const std::string lidar_near_file = "./lidar_near"; const std::string lidar_near_file = "./lidar_near";
const std::string lidar_far_file = "./lidar_far"; const std::string lidar_far_file = "./lidar_far";
const std::string lidar_near_start_file = "./lidar_near_start"; const std::string lidar_near_start_file = "./lidar_near_start";
const std::string lidar_near_end_file = "./lidar_near_end"; const std::string lidar_near_end_file = "./lidar_near_end";
const std::string lidar_far_span_file = "./lidar_far_span"; const std::string lidar_far_span_file = "./lidar_far_span";
const std::string lidar_min_frames_file = "./lidar_min_frames"; const std::string lidar_min_frames_file = "./lidar_min_frames";
const std::string lidar_avoid_gain_file = "./lidar_avoid_gain"; const std::string lidar_avoid_gain_file = "./lidar_avoid_gain";
const std::string lidar_avoid_range_file = "./lidar_avoid_range"; const std::string lidar_avoid_range_file = "./lidar_avoid_range";
const std::string lidar_speed_file = "./lidar_speed"; const std::string lidar_speed_file = "./lidar_speed";
const std::string lidar_hold_frames_file = "./lidar_hold_frames"; const std::string lidar_hold_frames_file = "./lidar_hold_frames";
const std::string lidar_enable_file = "./lidar_enable"; const std::string lidar_enable_file = "./lidar_enable";
double readDoubleFromFile(const std::string &filename); double readDoubleFromFile(const std::string &filename);
bool readFlag(const std::string &filename); bool readFlag(const std::string &filename);
void cfg_load_all(); void cfg_load_all();
// ── 启动时缓存的运行参数 ── // ── 启动时缓存的运行参数 ──
struct CfgCache { struct CfgCache {
double speed = 60; // 目标速度(占空比 %) double speed = 60; // 目标速度(占空比 %)
double foresee = 80; // 前瞻行 double foresee = 80; // 前瞻行
double foresee_lost_scale = 0.7; // 丢线时前瞻缩放 (<1=看更远) double foresee_lost_scale = 0.7; // 丢线时前瞻缩放 (<1=看更远)
double sharp_turn_scale = 0.5; // 急弯时前瞻缩放 (<1=看更远) double sharp_turn_scale = 0.5; // 急弯时前瞻缩放 (<1=看更远)
double zebrasee = 60; // 斑马线触发距离阈值 double zebrasee = 60; // 斑马线触发距离阈值
double deadband = 5; // 舵机死区 double deadband = 5; // 舵机死区
double steer_gain = 1.0; // 舵机增益 double steer_gain = 1.0; // 舵机增益
double center_bias = 0; // 中线偏移修正 double center_bias = 0; // 中线偏移修正
int start = 0; // 1=启动 0=停止 int start = 0; // 1=启动 0=停止
int showImg = 0; // LCD 预览开关 int showImg = 0; // LCD 预览开关
int debug = 0; // debug 模式 int debug = 0; // debug 模式
double cone_avoid_gain = 0.3; // 锥桶中线变形推离量 (归一化) double cone_avoid_gain = 0.3; // 锥桶中线变形推离量 (归一化)
int cone_avoid_range = 30; // 变形斜坡陡峭度 int cone_avoid_range = 30; // 变形斜坡陡峭度
double cone_speed = 0.5; // 锥桶触发时速度倍率 double cone_speed = 0.5; // 锥桶触发时速度倍率
int cone_min_frames = 1; // 确认帧数 (1=单帧即确认, 视觉巡线响应快导致检测窗口极短) int cone_min_frames = 1; // 确认帧数 (1=单帧即确认, 视觉巡线响应快导致检测窗口极短)
int cone_margin = 0; // 0=中心点 1=框边缘 int cone_margin = 0; // 0=中心点 1=框边缘
double cone_thresh = 0.80; // 锥桶置信度阈值 double cone_thresh = 0.80; // 锥桶置信度阈值
int cone_hold_frames = 15; // 锥桶消失后保持变形的帧数 int cone_hold_frames = 15; // 锥桶消失后保持变形的帧数
double cone_return_gain = 1.0; // 回弹力度 (倍乘, 1.0=等同于避让力度) double cone_return_gain = 1.0; // 回弹力度 (倍乘, 1.0=等同于避让力度)
int cone_return_frames = 30; // 回弹持续帧数 int cone_return_frames = 30; // 回弹持续帧数
double brake_scale = 10; // 速度(pps) → 刹车占空比(ns) 缩放系数 double brake_scale = 10; // 速度(pps) → 刹车占空比(ns) 缩放系数
int brake_max = 10000; // 最大刹车占空比 (ns) int brake_max = 10000; // 最大刹车占空比 (ns)
double curve_slope = 0.4; // 弯道减速斜率 (越大越猛) double curve_slope = 0.4; // 弯道减速斜率 (越大越猛)
double curve_min = 0.8; // 弯道最低速度倍率 double curve_min = 0.8; // 弯道最低速度倍率
int lidar_thresh = 300; // 激光障碍判定距离阈值 (mm), 必须<此值才触发 int lidar_thresh = 300; // 激光障碍判定距离阈值 (mm), 必须<此值才触发
int lidar_pre = 800; // 预触发去抖窗口, <此值开始攒帧 int lidar_pre = 800; // 预触发去抖窗口, <此值开始攒帧
int lidar_near = 50; // row=lt_h-1 对应的物理距离 (mm) int lidar_near = 50; // row=lt_h-1 对应的物理距离 (mm)
int lidar_far = 1200; // row=10 对应的物理距离 (mm) int lidar_far = 1200; // row=10 对应的物理距离 (mm)
int lidar_near_start = 1; // near_valid 检测起始偏移 int lidar_near_start = 1; // near_valid 检测起始偏移
int lidar_near_end = 4; // near_valid 检测终止偏移 int lidar_near_end = 4; // near_valid 检测终止偏移
int lidar_far_span = 6; // far_lost 检测跨度 int lidar_far_span = 6; // far_lost 检测跨度
int lidar_min_frames = 3; // 连续确认帧数 int lidar_min_frames = 3; // 连续确认帧数
double lidar_avoid_gain = 0.4; // 绕行中线推离力度 (归一化) double lidar_avoid_gain = 0.4; // 绕行中线推离力度 (归一化)
int lidar_avoid_range = 30; // 绕行斜坡陡峭度 (行数) int lidar_avoid_range = 30; // 绕行斜坡陡峭度 (行数)
double lidar_speed = 0.4; // 绕行时速度倍率 double lidar_speed = 0.4; // 绕行时速度倍率
int lidar_hold_frames = 30; // 消失后变形保持帧数 int lidar_hold_frames = 30; // 消失后变形保持帧数
int lidar_enable = 1; // 激光避障总开关 int lidar_enable = 1; // 激光避障总开关
}; };
extern CfgCache g_cfg; extern CfgCache g_cfg;
extern double target_speed; extern double target_speed;
#endif #endif
+28 -28
View File
@@ -1,28 +1,28 @@
#ifndef VL53L0X_H #ifndef VL53L0X_H
#define VL53L0X_H #define VL53L0X_H
#include <cstdint> #include <cstdint>
extern "C" { extern "C" {
#include "vl53l0x_platform.h" #include "vl53l0x_platform.h"
} }
class VL53L0X class VL53L0X
{ {
public: public:
VL53L0X(); VL53L0X();
~VL53L0X(); ~VL53L0X();
bool init(); bool init();
bool startMeasure(); bool startMeasure();
bool readResult(VL53L0X_RangingMeasurementData_t &data); bool readResult(VL53L0X_RangingMeasurementData_t &data);
bool readRange(VL53L0X_RangingMeasurementData_t &data); bool readRange(VL53L0X_RangingMeasurementData_t &data);
bool stop(); bool stop();
private: private:
int fd; int fd;
bool initialized; bool initialized;
vl53l0x_dev_t dev; vl53l0x_dev_t dev;
}; };
#endif #endif
+640 -640
View File
File diff suppressed because it is too large Load Diff
+257 -257
View File
@@ -1,257 +1,257 @@
/******************************************************************************* /*******************************************************************************
Copyright © 2016, STMicroelectronics International N.V. Copyright © 2016, STMicroelectronics International N.V.
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of STMicroelectronics nor the * Neither the name of STMicroelectronics nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/ *******************************************************************************/
/** /**
* Device specific defines. To be adapted by implementer for the targeted * Device specific defines. To be adapted by implementer for the targeted
* device. * device.
*/ */
#ifndef _VL53L0X_DEVICE_H_ #ifndef _VL53L0X_DEVICE_H_
#define _VL53L0X_DEVICE_H_ #define _VL53L0X_DEVICE_H_
#include "vl53l0x_types.h" #include "vl53l0x_types.h"
/** @defgroup VL53L0X_DevSpecDefines_group VL53L0X cut1.1 Device Specific Defines /** @defgroup VL53L0X_DevSpecDefines_group VL53L0X cut1.1 Device Specific Defines
* @brief VL53L0X cut1.1 Device Specific Defines * @brief VL53L0X cut1.1 Device Specific Defines
* @{ * @{
*/ */
/** @defgroup VL53L0X_DeviceError_group Device Error /** @defgroup VL53L0X_DeviceError_group Device Error
* @brief Device Error code * @brief Device Error code
* *
* This enum is Device specific it should be updated in the implementation * This enum is Device specific it should be updated in the implementation
* Use @a VL53L0X_GetStatusErrorString() to get the string. * Use @a VL53L0X_GetStatusErrorString() to get the string.
* It is related to Status Register of the Device. * It is related to Status Register of the Device.
* @{ * @{
*/ */
typedef uint8_t VL53L0X_DeviceError; typedef uint8_t VL53L0X_DeviceError;
#define VL53L0X_DEVICEERROR_NONE ((VL53L0X_DeviceError) 0) #define VL53L0X_DEVICEERROR_NONE ((VL53L0X_DeviceError) 0)
/*!< 0 NoError */ /*!< 0 NoError */
#define VL53L0X_DEVICEERROR_VCSELCONTINUITYTESTFAILURE ((VL53L0X_DeviceError) 1) #define VL53L0X_DEVICEERROR_VCSELCONTINUITYTESTFAILURE ((VL53L0X_DeviceError) 1)
#define VL53L0X_DEVICEERROR_VCSELWATCHDOGTESTFAILURE ((VL53L0X_DeviceError) 2) #define VL53L0X_DEVICEERROR_VCSELWATCHDOGTESTFAILURE ((VL53L0X_DeviceError) 2)
#define VL53L0X_DEVICEERROR_NOVHVVALUEFOUND ((VL53L0X_DeviceError) 3) #define VL53L0X_DEVICEERROR_NOVHVVALUEFOUND ((VL53L0X_DeviceError) 3)
#define VL53L0X_DEVICEERROR_MSRCNOTARGET ((VL53L0X_DeviceError) 4) #define VL53L0X_DEVICEERROR_MSRCNOTARGET ((VL53L0X_DeviceError) 4)
#define VL53L0X_DEVICEERROR_SNRCHECK ((VL53L0X_DeviceError) 5) #define VL53L0X_DEVICEERROR_SNRCHECK ((VL53L0X_DeviceError) 5)
#define VL53L0X_DEVICEERROR_RANGEPHASECHECK ((VL53L0X_DeviceError) 6) #define VL53L0X_DEVICEERROR_RANGEPHASECHECK ((VL53L0X_DeviceError) 6)
#define VL53L0X_DEVICEERROR_SIGMATHRESHOLDCHECK ((VL53L0X_DeviceError) 7) #define VL53L0X_DEVICEERROR_SIGMATHRESHOLDCHECK ((VL53L0X_DeviceError) 7)
#define VL53L0X_DEVICEERROR_TCC ((VL53L0X_DeviceError) 8) #define VL53L0X_DEVICEERROR_TCC ((VL53L0X_DeviceError) 8)
#define VL53L0X_DEVICEERROR_PHASECONSISTENCY ((VL53L0X_DeviceError) 9) #define VL53L0X_DEVICEERROR_PHASECONSISTENCY ((VL53L0X_DeviceError) 9)
#define VL53L0X_DEVICEERROR_MINCLIP ((VL53L0X_DeviceError) 10) #define VL53L0X_DEVICEERROR_MINCLIP ((VL53L0X_DeviceError) 10)
#define VL53L0X_DEVICEERROR_RANGECOMPLETE ((VL53L0X_DeviceError) 11) #define VL53L0X_DEVICEERROR_RANGECOMPLETE ((VL53L0X_DeviceError) 11)
#define VL53L0X_DEVICEERROR_ALGOUNDERFLOW ((VL53L0X_DeviceError) 12) #define VL53L0X_DEVICEERROR_ALGOUNDERFLOW ((VL53L0X_DeviceError) 12)
#define VL53L0X_DEVICEERROR_ALGOOVERFLOW ((VL53L0X_DeviceError) 13) #define VL53L0X_DEVICEERROR_ALGOOVERFLOW ((VL53L0X_DeviceError) 13)
#define VL53L0X_DEVICEERROR_RANGEIGNORETHRESHOLD ((VL53L0X_DeviceError) 14) #define VL53L0X_DEVICEERROR_RANGEIGNORETHRESHOLD ((VL53L0X_DeviceError) 14)
/** @} end of VL53L0X_DeviceError_group */ /** @} end of VL53L0X_DeviceError_group */
/** @defgroup VL53L0X_CheckEnable_group Check Enable list /** @defgroup VL53L0X_CheckEnable_group Check Enable list
* @brief Check Enable code * @brief Check Enable code
* *
* Define used to specify the LimitCheckId. * Define used to specify the LimitCheckId.
* Use @a VL53L0X_GetLimitCheckInfo() to get the string. * Use @a VL53L0X_GetLimitCheckInfo() to get the string.
* @{ * @{
*/ */
#define VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE 0 #define VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE 0
#define VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE 1 #define VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE 1
#define VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP 2 #define VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP 2
#define VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD 3 #define VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD 3
#define VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC 4 #define VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC 4
#define VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE 5 #define VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE 5
#define VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS 6 #define VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS 6
/** @} end of VL53L0X_CheckEnable_group */ /** @} end of VL53L0X_CheckEnable_group */
/** @defgroup VL53L0X_GpioFunctionality_group Gpio Functionality /** @defgroup VL53L0X_GpioFunctionality_group Gpio Functionality
* @brief Defines the different functionalities for the device GPIO(s) * @brief Defines the different functionalities for the device GPIO(s)
* @{ * @{
*/ */
typedef uint8_t VL53L0X_GpioFunctionality; typedef uint8_t VL53L0X_GpioFunctionality;
#define VL53L0X_GPIOFUNCTIONALITY_OFF \ #define VL53L0X_GPIOFUNCTIONALITY_OFF \
((VL53L0X_GpioFunctionality) 0) /*!< NO Interrupt */ ((VL53L0X_GpioFunctionality) 0) /*!< NO Interrupt */
#define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW \ #define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW \
((VL53L0X_GpioFunctionality) 1) /*!< Level Low (value < thresh_low) */ ((VL53L0X_GpioFunctionality) 1) /*!< Level Low (value < thresh_low) */
#define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH \ #define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH \
((VL53L0X_GpioFunctionality) 2) /*!< Level High (value > thresh_high) */ ((VL53L0X_GpioFunctionality) 2) /*!< Level High (value > thresh_high) */
#define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT \ #define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT \
((VL53L0X_GpioFunctionality) 3) ((VL53L0X_GpioFunctionality) 3)
/*!< Out Of Window (value < thresh_low OR value > thresh_high) */ /*!< Out Of Window (value < thresh_low OR value > thresh_high) */
#define VL53L0X_GPIOFUNCTIONALITY_NEW_MEASURE_READY \ #define VL53L0X_GPIOFUNCTIONALITY_NEW_MEASURE_READY \
((VL53L0X_GpioFunctionality) 4) /*!< New Sample Ready */ ((VL53L0X_GpioFunctionality) 4) /*!< New Sample Ready */
/** @} end of VL53L0X_GpioFunctionality_group */ /** @} end of VL53L0X_GpioFunctionality_group */
/* Device register map */ /* Device register map */
/** @defgroup VL53L0X_DefineRegisters_group Define Registers /** @defgroup VL53L0X_DefineRegisters_group Define Registers
* @brief List of all the defined registers * @brief List of all the defined registers
* @{ * @{
*/ */
#define VL53L0X_REG_SYSRANGE_START 0x000 #define VL53L0X_REG_SYSRANGE_START 0x000
/** mask existing bit in #VL53L0X_REG_SYSRANGE_START*/ /** mask existing bit in #VL53L0X_REG_SYSRANGE_START*/
#define VL53L0X_REG_SYSRANGE_MODE_MASK 0x0F #define VL53L0X_REG_SYSRANGE_MODE_MASK 0x0F
/** bit 0 in #VL53L0X_REG_SYSRANGE_START write 1 toggle state in /** bit 0 in #VL53L0X_REG_SYSRANGE_START write 1 toggle state in
* continuous mode and arm next shot in single shot mode */ * continuous mode and arm next shot in single shot mode */
#define VL53L0X_REG_SYSRANGE_MODE_START_STOP 0x01 #define VL53L0X_REG_SYSRANGE_MODE_START_STOP 0x01
/** bit 1 write 0 in #VL53L0X_REG_SYSRANGE_START set single shot mode */ /** bit 1 write 0 in #VL53L0X_REG_SYSRANGE_START set single shot mode */
#define VL53L0X_REG_SYSRANGE_MODE_SINGLESHOT 0x00 #define VL53L0X_REG_SYSRANGE_MODE_SINGLESHOT 0x00
/** bit 1 write 1 in #VL53L0X_REG_SYSRANGE_START set back-to-back /** bit 1 write 1 in #VL53L0X_REG_SYSRANGE_START set back-to-back
* operation mode */ * operation mode */
#define VL53L0X_REG_SYSRANGE_MODE_BACKTOBACK 0x02 #define VL53L0X_REG_SYSRANGE_MODE_BACKTOBACK 0x02
/** bit 2 write 1 in #VL53L0X_REG_SYSRANGE_START set timed operation /** bit 2 write 1 in #VL53L0X_REG_SYSRANGE_START set timed operation
* mode */ * mode */
#define VL53L0X_REG_SYSRANGE_MODE_TIMED 0x04 #define VL53L0X_REG_SYSRANGE_MODE_TIMED 0x04
/** bit 3 write 1 in #VL53L0X_REG_SYSRANGE_START set histogram operation /** bit 3 write 1 in #VL53L0X_REG_SYSRANGE_START set histogram operation
* mode */ * mode */
#define VL53L0X_REG_SYSRANGE_MODE_HISTOGRAM 0x08 #define VL53L0X_REG_SYSRANGE_MODE_HISTOGRAM 0x08
#define VL53L0X_REG_SYSTEM_THRESH_HIGH 0x000C #define VL53L0X_REG_SYSTEM_THRESH_HIGH 0x000C
#define VL53L0X_REG_SYSTEM_THRESH_LOW 0x000E #define VL53L0X_REG_SYSTEM_THRESH_LOW 0x000E
#define VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG 0x0001 #define VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG 0x0001
#define VL53L0X_REG_SYSTEM_RANGE_CONFIG 0x0009 #define VL53L0X_REG_SYSTEM_RANGE_CONFIG 0x0009
#define VL53L0X_REG_SYSTEM_INTERMEASUREMENT_PERIOD 0x0004 #define VL53L0X_REG_SYSTEM_INTERMEASUREMENT_PERIOD 0x0004
#define VL53L0X_REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x000A #define VL53L0X_REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x000A
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_DISABLED 0x00 #define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_DISABLED 0x00
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_LOW 0x01 #define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_LOW 0x01
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_HIGH 0x02 #define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_HIGH 0x02
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_OUT_OF_WINDOW 0x03 #define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_OUT_OF_WINDOW 0x03
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY 0x04 #define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY 0x04
#define VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH 0x0084 #define VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH 0x0084
#define VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR 0x000B #define VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR 0x000B
/* Result registers */ /* Result registers */
#define VL53L0X_REG_RESULT_INTERRUPT_STATUS 0x0013 #define VL53L0X_REG_RESULT_INTERRUPT_STATUS 0x0013
#define VL53L0X_REG_RESULT_RANGE_STATUS 0x0014 #define VL53L0X_REG_RESULT_RANGE_STATUS 0x0014
#define VL53L0X_REG_RESULT_CORE_PAGE 1 #define VL53L0X_REG_RESULT_CORE_PAGE 1
#define VL53L0X_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN 0x00BC #define VL53L0X_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN 0x00BC
#define VL53L0X_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_RTN 0x00C0 #define VL53L0X_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_RTN 0x00C0
#define VL53L0X_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF 0x00D0 #define VL53L0X_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF 0x00D0
#define VL53L0X_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_REF 0x00D4 #define VL53L0X_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_REF 0x00D4
#define VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF 0x00B6 #define VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF 0x00B6
/* Algo register */ /* Algo register */
#define VL53L0X_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM 0x0028 #define VL53L0X_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM 0x0028
#define VL53L0X_REG_I2C_SLAVE_DEVICE_ADDRESS 0x008a #define VL53L0X_REG_I2C_SLAVE_DEVICE_ADDRESS 0x008a
/* Check Limit registers */ /* Check Limit registers */
#define VL53L0X_REG_MSRC_CONFIG_CONTROL 0x0060 #define VL53L0X_REG_MSRC_CONFIG_CONTROL 0x0060
#define VL53L0X_REG_PRE_RANGE_CONFIG_MIN_SNR 0X0027 #define VL53L0X_REG_PRE_RANGE_CONFIG_MIN_SNR 0X0027
#define VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW 0x0056 #define VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW 0x0056
#define VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH 0x0057 #define VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH 0x0057
#define VL53L0X_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT 0x0064 #define VL53L0X_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT 0x0064
#define VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_SNR 0X0067 #define VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_SNR 0X0067
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW 0x0047 #define VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW 0x0047
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH 0x0048 #define VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH 0x0048
#define VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT 0x0044 #define VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT 0x0044
#define VL53L0X_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_HI 0X0061 #define VL53L0X_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_HI 0X0061
#define VL53L0X_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_LO 0X0062 #define VL53L0X_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_LO 0X0062
/* PRE RANGE registers */ /* PRE RANGE registers */
#define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD 0x0050 #define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD 0x0050
#define VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x0051 #define VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x0051
#define VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x0052 #define VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x0052
#define VL53L0X_REG_SYSTEM_HISTOGRAM_BIN 0x0081 #define VL53L0X_REG_SYSTEM_HISTOGRAM_BIN 0x0081
#define VL53L0X_REG_HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT 0x0033 #define VL53L0X_REG_HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT 0x0033
#define VL53L0X_REG_HISTOGRAM_CONFIG_READOUT_CTRL 0x0055 #define VL53L0X_REG_HISTOGRAM_CONFIG_READOUT_CTRL 0x0055
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x0070 #define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x0070
#define VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x0071 #define VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x0071
#define VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x0072 #define VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x0072
#define VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS 0x0020 #define VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS 0x0020
#define VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP 0x0046 #define VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP 0x0046
#define VL53L0X_REG_SOFT_RESET_GO2_SOFT_RESET_N 0x00bf #define VL53L0X_REG_SOFT_RESET_GO2_SOFT_RESET_N 0x00bf
#define VL53L0X_REG_IDENTIFICATION_MODEL_ID 0x00c0 #define VL53L0X_REG_IDENTIFICATION_MODEL_ID 0x00c0
#define VL53L0X_REG_IDENTIFICATION_REVISION_ID 0x00c2 #define VL53L0X_REG_IDENTIFICATION_REVISION_ID 0x00c2
#define VL53L0X_REG_OSC_CALIBRATE_VAL 0x00f8 #define VL53L0X_REG_OSC_CALIBRATE_VAL 0x00f8
#define VL53L0X_SIGMA_ESTIMATE_MAX_VALUE 65535 #define VL53L0X_SIGMA_ESTIMATE_MAX_VALUE 65535
/* equivalent to a range sigma of 655.35mm */ /* equivalent to a range sigma of 655.35mm */
#define VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH 0x032 #define VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH 0x032
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0 0x0B0 #define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0 0x0B0
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_1 0x0B1 #define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_1 0x0B1
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_2 0x0B2 #define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_2 0x0B2
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_3 0x0B3 #define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_3 0x0B3
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_4 0x0B4 #define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_4 0x0B4
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_5 0x0B5 #define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_5 0x0B5
#define VL53L0X_REG_GLOBAL_CONFIG_REF_EN_START_SELECT 0xB6 #define VL53L0X_REG_GLOBAL_CONFIG_REF_EN_START_SELECT 0xB6
#define VL53L0X_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD 0x4E /* 0x14E */ #define VL53L0X_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD 0x4E /* 0x14E */
#define VL53L0X_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET 0x4F /* 0x14F */ #define VL53L0X_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET 0x4F /* 0x14F */
#define VL53L0X_REG_POWER_MANAGEMENT_GO1_POWER_FORCE 0x80 #define VL53L0X_REG_POWER_MANAGEMENT_GO1_POWER_FORCE 0x80
/* /*
* Speed of light in um per 1E-10 Seconds * Speed of light in um per 1E-10 Seconds
*/ */
#define VL53L0X_SPEED_OF_LIGHT_IN_AIR 2997 #define VL53L0X_SPEED_OF_LIGHT_IN_AIR 2997
#define VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV 0x0089 #define VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV 0x0089
#define VL53L0X_REG_ALGO_PHASECAL_LIM 0x0030 /* 0x130 */ #define VL53L0X_REG_ALGO_PHASECAL_LIM 0x0030 /* 0x130 */
#define VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT 0x0030 #define VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT 0x0030
/** @} VL53L0X_DefineRegisters_group */ /** @} VL53L0X_DefineRegisters_group */
/** @} VL53L0X_DevSpecDefines_group */ /** @} VL53L0X_DevSpecDefines_group */
#endif #endif
/* _VL53L0X_DEVICE_H_ */ /* _VL53L0X_DEVICE_H_ */
-16
View File
@@ -1,16 +0,0 @@
/*
* zebra_detect.h — 斑马线检测函数
* ================================
* 输入图片 → 返回是否有人行横道 + 距离
*/
#pragma once
#include <opencv2/opencv.hpp>
struct ZebraResult
{
bool detected; // true = 检测到斑马线
int distance_px; // 斑马线下沿距图像下边框的像素距离, -1 = 未检测到
};
ZebraResult detect_zebra_crossing(const cv::Mat &bgr_frame);
-3
View File
@@ -7,6 +7,3 @@ target_link_libraries(lidar_test common_lib)
add_executable(remote_control remote_control.cpp) add_executable(remote_control remote_control.cpp)
target_link_libraries(remote_control common_lib) target_link_libraries(remote_control common_lib)
add_executable(lcd_test lcd_test.cpp)
target_link_libraries(lcd_test common_lib ${OpenCV_LIBS})
+44 -44
View File
@@ -1,44 +1,44 @@
#include <iostream> #include <iostream>
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#include <csignal> #include <csignal>
#include <atomic> #include <atomic>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include <sched.h> #include <sched.h>
#include <sys/resource.h> #include <sys/resource.h>
#include "global.h" #include "global.h"
#include "camera.h" #include "camera.h"
#include "control.h" #include "control.h"
std::atomic<bool> running(true); std::atomic<bool> running(true);
void signalHandler(int) { running.store(false); } void signalHandler(int) { running.store(false); }
int main(void) int main(void)
{ {
std::signal(SIGINT, signalHandler); std::signal(SIGINT, signalHandler);
cfg_load_all(); cfg_load_all();
if (CameraInit(0) < 0) { if (CameraInit(0) < 0) {
std::cerr << "CameraInit failed" << std::endl; std::cerr << "CameraInit failed" << std::endl;
return -1; return -1;
} }
ControlInit(); ControlInit();
std::cout << "All services started" << std::endl; std::cout << "All services started" << std::endl;
setpriority(PRIO_PROCESS, 0, -10); setpriority(PRIO_PROCESS, 0, -10);
while (running.load()) { while (running.load()) {
CameraHandler(); CameraHandler();
target_speed = g_cfg.speed; target_speed = g_cfg.speed;
sched_yield(); sched_yield();
} }
std::cout << "Stopping..." << std::endl; std::cout << "Stopping..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::this_thread::sleep_for(std::chrono::milliseconds(500));
ControlExit(); ControlExit();
cameraDeInit(); cameraDeInit();
std::cout << "Stopped." << std::endl; std::cout << "Stopped." << std::endl;
return 0; return 0;
} }
+15 -80
View File
@@ -25,7 +25,6 @@
#include "camera.h" #include "camera.h"
#include "model_v10.hpp" #include "model_v10.hpp"
#include "vl53l0x.h" #include "vl53l0x.h"
#include "font_bitmap.h"
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@@ -218,76 +217,6 @@ static void play_zebra_audio()
} }
// ═══════════════════════════════════════════════════════════
// LCD 中文文字渲染
//
// 使用 src/font_bitmap.h 中嵌入的 16x16 字模
// ═══════════════════════════════════════════════════════════
static const uint8_t* find_glyph(uint32_t codepoint)
{
for (int i = 0; i < FONT_GLYPH_COUNT; ++i)
if (FONT_GLYPHS[i].unicode == codepoint) return FONT_GLYPHS[i].bitmap;
return nullptr;
}
static uint32_t utf8_decode(const char*& p)
{
unsigned char c = static_cast<unsigned char>(*p);
if (c == 0) return 0;
if ((c & 0x80) == 0) { ++p; return c; }
if ((c & 0xE0) == 0xC0) {
uint32_t v = c & 0x1F; ++p;
v = (v << 6) | (static_cast<unsigned char>(*p++) & 0x3F);
return v;
}
if ((c & 0xF0) == 0xE0) {
uint32_t v = c & 0x0F; ++p;
v = (v << 6) | (static_cast<unsigned char>(*p++) & 0x3F);
v = (v << 6) | (static_cast<unsigned char>(*p++) & 0x3F);
return v;
}
if ((c & 0xF8) == 0xF0) {
uint32_t v = c & 0x07; ++p;
v = (v << 6) | (static_cast<unsigned char>(*p++) & 0x3F);
v = (v << 6) | (static_cast<unsigned char>(*p++) & 0x3F);
v = (v << 6) | (static_cast<unsigned char>(*p++) & 0x3F);
return v;
}
++p;
return '?';
}
static void lcd_draw_glyph(cv::Mat& img, int x0, int y0, const uint8_t* glyph, const cv::Scalar& color)
{
for (int row = 0; row < FONT_SIZE; ++row) {
for (int col = 0; col < FONT_SIZE; ++col) {
if (glyph[row * FONT_SIZE + col] > 128) {
int px = x0 + col;
int py = y0 + row;
if (px >= 0 && px < img.cols && py >= 0 && py < img.rows)
img.at<cv::Vec3b>(py, px) = cv::Vec3b(static_cast<uchar>(color[0]),
static_cast<uchar>(color[1]),
static_cast<uchar>(color[2]));
}
}
}
}
static void lcd_draw_chinese_text(cv::Mat& img, const char* text, int x, int y, const cv::Scalar& color)
{
const char* p = text;
int cx = x;
while (*p) {
uint32_t cp = utf8_decode(p);
const uint8_t* glyph = find_glyph(cp);
if (glyph) {
lcd_draw_glyph(img, cx, y, glyph, color);
cx += FONT_SIZE;
}
}
}
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
// CameraInit — 系统初始化 // CameraInit — 系统初始化
// //
@@ -1033,12 +962,15 @@ static void steering_update()
} }
} }
if (std::abs(deviation) < g_cfg.deadband) { // 平滑线性转向: 偏差从死区边界开始缩放,消除死区断崖
// 死区内 → 直行 double effective = std::abs(deviation) - g_cfg.deadband;
if (effective <= 0) {
servo.setDutyCycle(1500000); servo.setDutyCycle(1500000);
} else { } else {
// 比例控制: 偏差 → 归一化 → × 增益 × 满偏占空比差 double half_w = newWidth / 2.0;
double offset = deviation / (newWidth / 2.0) * g_cfg.steer_gain * 300000; double norm = effective / (half_w - g_cfg.deadband);
double sign = (deviation > 0) ? 1.0 : -1.0;
double offset = norm * g_cfg.steer_gain * 300000.0 * sign;
double duty_ns = std::clamp(1500000.0 + offset, 1200000.0, 1800000.0); double duty_ns = std::clamp(1500000.0 + offset, 1200000.0, 1800000.0);
servo.setDutyCycle((unsigned int)duty_ns); servo.setDutyCycle((unsigned int)duty_ns);
} }
@@ -1102,13 +1034,16 @@ static void motor_update(bool zebra_block, bool tl_block)
prev_zstate = g_zstate; prev_zstate = g_zstate;
prev_tlstate = g_tl_state; prev_tlstate = g_tl_state;
double spd = target_speed * boost_factor(); double spd;
if (boost_factor() > 1.0) {
// 斑马线起步后 3.3~5s 降速走稳 spd = 26.0; // 起步弹射
if (g_zstate == Z_COOLDOWN) { } else if (g_zstate == Z_COOLDOWN) {
spd = 16.0; // 冷却期基础速度
time_t elapsed = time(nullptr) - g_ztime; time_t elapsed = time(nullptr) - g_ztime;
if (elapsed >= 3.3 && elapsed < 5) if (elapsed >= 3.3 && elapsed < 5)
spd = std::min(spd, 13.0); spd = std::min(spd, 13.0); // 3.3~5s 降速
} else {
spd = target_speed; // 正常行驶
} }
// 弯道减速: 舵机偏差越大 → 速度越低 // 弯道减速: 舵机偏差越大 → 速度越低
+66 -66
View File
@@ -1,66 +1,66 @@
#include "global.h" #include "global.h"
#include <fstream> #include <fstream>
CfgCache g_cfg; CfgCache g_cfg;
double target_speed; double target_speed;
double readDoubleFromFile(const std::string &filename) double readDoubleFromFile(const std::string &filename)
{ {
std::ifstream file(filename); std::ifstream file(filename);
double value = 0.0; double value = 0.0;
if (file.is_open()) { file >> value; file.close(); } if (file.is_open()) { file >> value; file.close(); }
return value; return value;
} }
bool readFlag(const std::string &filename) bool readFlag(const std::string &filename)
{ {
std::ifstream file(filename); std::ifstream file(filename);
int flag = 0; int flag = 0;
if (file.is_open()) { file >> flag; file.close(); } if (file.is_open()) { file >> flag; file.close(); }
return flag; return flag;
} }
void cfg_load_all() void cfg_load_all()
{ {
g_cfg.speed = readDoubleFromFile(speed_file); g_cfg.speed = readDoubleFromFile(speed_file);
g_cfg.foresee = readDoubleFromFile(foresee_file); g_cfg.foresee = readDoubleFromFile(foresee_file);
g_cfg.foresee_lost_scale = readDoubleFromFile(foresee_lost_scale_file); g_cfg.foresee_lost_scale = readDoubleFromFile(foresee_lost_scale_file);
g_cfg.sharp_turn_scale = readDoubleFromFile(sharp_turn_scale_file); g_cfg.sharp_turn_scale = readDoubleFromFile(sharp_turn_scale_file);
g_cfg.zebrasee = readDoubleFromFile(zebrasee_file); g_cfg.zebrasee = readDoubleFromFile(zebrasee_file);
g_cfg.deadband = readDoubleFromFile(deadband_file); g_cfg.deadband = readDoubleFromFile(deadband_file);
g_cfg.steer_gain = readDoubleFromFile(steer_gain_file); g_cfg.steer_gain = readDoubleFromFile(steer_gain_file);
g_cfg.center_bias = readDoubleFromFile(center_bias_file); g_cfg.center_bias = readDoubleFromFile(center_bias_file);
g_cfg.start = readFlag(start_file); g_cfg.start = readFlag(start_file);
g_cfg.showImg = readFlag(showImg_file); g_cfg.showImg = readFlag(showImg_file);
g_cfg.debug = readFlag(debug_file); g_cfg.debug = readFlag(debug_file);
g_cfg.cone_speed = readDoubleFromFile(cone_speed_file); g_cfg.cone_speed = readDoubleFromFile(cone_speed_file);
g_cfg.cone_min_frames = (int)readDoubleFromFile(cone_min_frames_file); g_cfg.cone_min_frames = (int)readDoubleFromFile(cone_min_frames_file);
g_cfg.cone_margin = (int)readDoubleFromFile(cone_margin_file); g_cfg.cone_margin = (int)readDoubleFromFile(cone_margin_file);
g_cfg.cone_thresh = readDoubleFromFile(cone_thresh_file); g_cfg.cone_thresh = readDoubleFromFile(cone_thresh_file);
g_cfg.cone_avoid_gain = readDoubleFromFile(cone_avoid_gain_file); g_cfg.cone_avoid_gain = readDoubleFromFile(cone_avoid_gain_file);
g_cfg.cone_avoid_range = (int)readDoubleFromFile(cone_avoid_range_file); g_cfg.cone_avoid_range = (int)readDoubleFromFile(cone_avoid_range_file);
g_cfg.cone_hold_frames = (int)readDoubleFromFile(cone_hold_frames_file); g_cfg.cone_hold_frames = (int)readDoubleFromFile(cone_hold_frames_file);
g_cfg.cone_return_gain = readDoubleFromFile(cone_return_gain_file); g_cfg.cone_return_gain = readDoubleFromFile(cone_return_gain_file);
g_cfg.cone_return_frames = (int)readDoubleFromFile(cone_return_frames_file); g_cfg.cone_return_frames = (int)readDoubleFromFile(cone_return_frames_file);
g_cfg.brake_scale = readDoubleFromFile(brake_scale_file); g_cfg.brake_scale = readDoubleFromFile(brake_scale_file);
g_cfg.brake_max = readDoubleFromFile(brake_max_file); g_cfg.brake_max = readDoubleFromFile(brake_max_file);
g_cfg.curve_slope = readDoubleFromFile(curve_slope_file); g_cfg.curve_slope = readDoubleFromFile(curve_slope_file);
g_cfg.curve_min = readDoubleFromFile(curve_min_file); g_cfg.curve_min = readDoubleFromFile(curve_min_file);
g_cfg.lidar_thresh = (int)readDoubleFromFile(lidar_thresh_file); g_cfg.lidar_thresh = (int)readDoubleFromFile(lidar_thresh_file);
g_cfg.lidar_pre = (int)readDoubleFromFile(lidar_pre_file); g_cfg.lidar_pre = (int)readDoubleFromFile(lidar_pre_file);
g_cfg.lidar_near = (int)readDoubleFromFile(lidar_near_file); g_cfg.lidar_near = (int)readDoubleFromFile(lidar_near_file);
g_cfg.lidar_far = (int)readDoubleFromFile(lidar_far_file); g_cfg.lidar_far = (int)readDoubleFromFile(lidar_far_file);
g_cfg.lidar_near_start = (int)readDoubleFromFile(lidar_near_start_file); g_cfg.lidar_near_start = (int)readDoubleFromFile(lidar_near_start_file);
g_cfg.lidar_near_end = (int)readDoubleFromFile(lidar_near_end_file); g_cfg.lidar_near_end = (int)readDoubleFromFile(lidar_near_end_file);
g_cfg.lidar_far_span = (int)readDoubleFromFile(lidar_far_span_file); g_cfg.lidar_far_span = (int)readDoubleFromFile(lidar_far_span_file);
g_cfg.lidar_min_frames = (int)readDoubleFromFile(lidar_min_frames_file); g_cfg.lidar_min_frames = (int)readDoubleFromFile(lidar_min_frames_file);
g_cfg.lidar_avoid_gain = readDoubleFromFile(lidar_avoid_gain_file); g_cfg.lidar_avoid_gain = readDoubleFromFile(lidar_avoid_gain_file);
g_cfg.lidar_avoid_range = (int)readDoubleFromFile(lidar_avoid_range_file); g_cfg.lidar_avoid_range = (int)readDoubleFromFile(lidar_avoid_range_file);
g_cfg.lidar_speed = readDoubleFromFile(lidar_speed_file); g_cfg.lidar_speed = readDoubleFromFile(lidar_speed_file);
g_cfg.lidar_hold_frames = (int)readDoubleFromFile(lidar_hold_frames_file); g_cfg.lidar_hold_frames = (int)readDoubleFromFile(lidar_hold_frames_file);
g_cfg.lidar_enable = (int)readDoubleFromFile(lidar_enable_file); g_cfg.lidar_enable = (int)readDoubleFromFile(lidar_enable_file);
} }
+10 -5
View File
@@ -69,10 +69,12 @@ cv::Mat image_binerize(cv::Mat &frame)
cv::cvtColor(frame, hsvImage, cv::COLOR_BGR2HSV); cv::cvtColor(frame, hsvImage, cv::COLOR_BGR2HSV);
cv::split(hsvImage, hsvChannels); cv::split(hsvImage, hsvChannels);
cv::threshold(hsvChannels[0], binarizedFrame, cv::adaptiveThreshold(hsvChannels[0], binarizedFrame, 255,
0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU); cv::ADAPTIVE_THRESH_GAUSSIAN_C,
cv::threshold(hsvChannels[1], output, cv::THRESH_BINARY_INV, 11, 2);
0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU); cv::adaptiveThreshold(hsvChannels[1], output, 255,
cv::ADAPTIVE_THRESH_GAUSSIAN_C,
cv::THRESH_BINARY_INV, 11, 2);
cv::bitwise_or(output, binarizedFrame, output); cv::bitwise_or(output, binarizedFrame, output);
@@ -104,7 +106,7 @@ cv::Mat image_binerize(cv::Mat &frame)
// ============================================================ // ============================================================
cv::Mat find_road(cv::Mat &frame) cv::Mat find_road(cv::Mat &frame)
{ {
static cv::Mat kernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3, 3)); static cv::Mat kernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(7, 7));
cv::morphologyEx(binarizedFrame, morphologyExFrame, cv::MORPH_OPEN, kernel); cv::morphologyEx(binarizedFrame, morphologyExFrame, cv::MORPH_OPEN, kernel);
static cv::Mat mask; static cv::Mat mask;
@@ -173,6 +175,9 @@ void image_main()
cv::merge(labCh, labFrame); cv::merge(labCh, labFrame);
cv::cvtColor(labFrame, resizedFrame, cv::COLOR_Lab2BGR); cv::cvtColor(labFrame, resizedFrame, cv::COLOR_Lab2BGR);
// ── 1.6 高斯模糊 → 融合反光噪点 ────────────────────
cv::GaussianBlur(resizedFrame, resizedFrame, cv::Size(5, 5), 0);
// ── 2. HSV 双通道 Otsu 二值化 ───────────────────── // ── 2. HSV 双通道 Otsu 二值化 ─────────────────────
// 赛道区域 = 白色(255),背景/边界 = 黑色(0) // 赛道区域 = 白色(255),背景/边界 = 黑色(0)
binarizedFrame = image_binerize(resizedFrame); binarizedFrame = image_binerize(resizedFrame);
+174 -174
View File
@@ -1,174 +1,174 @@
#include "vl53l0x.h" #include "vl53l0x.h"
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/i2c-dev.h> #include <linux/i2c-dev.h>
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <cerrno> #include <cerrno>
extern "C" { extern "C" {
#include "vl53l0x_api.h" #include "vl53l0x_api.h"
} }
static void unbind_kernel_driver() static void unbind_kernel_driver()
{ {
FILE *f = fopen("/sys/bus/i2c/drivers/stmvl53l0/unbind", "w"); FILE *f = fopen("/sys/bus/i2c/drivers/stmvl53l0/unbind", "w");
if (f) { if (f) {
fprintf(f, "1-0029"); fprintf(f, "1-0029");
fclose(f); fclose(f);
} }
} }
VL53L0X::VL53L0X() VL53L0X::VL53L0X()
: fd(-1), initialized(false) : fd(-1), initialized(false)
{ {
memset(&dev, 0, sizeof(dev)); memset(&dev, 0, sizeof(dev));
} }
VL53L0X::~VL53L0X() VL53L0X::~VL53L0X()
{ {
stop(); stop();
} }
bool VL53L0X::init() bool VL53L0X::init()
{ {
unbind_kernel_driver(); unbind_kernel_driver();
usleep(100000); usleep(100000);
fd = open("/dev/i2c-1", O_RDWR); fd = open("/dev/i2c-1", O_RDWR);
if (fd < 0) { if (fd < 0) {
fprintf(stderr, "[VL53L0X] open /dev/i2c-1 failed: %s\n", strerror(errno)); fprintf(stderr, "[VL53L0X] open /dev/i2c-1 failed: %s\n", strerror(errno));
return false; return false;
} }
if (ioctl(fd, I2C_SLAVE, 0x29) < 0) { if (ioctl(fd, I2C_SLAVE, 0x29) < 0) {
fprintf(stderr, "[VL53L0X] I2C_SLAVE failed: %s\n", strerror(errno)); fprintf(stderr, "[VL53L0X] I2C_SLAVE failed: %s\n", strerror(errno));
close(fd); close(fd);
fd = -1; fd = -1;
return false; return false;
} }
dev.I2cDevAddr = 0x29; dev.I2cDevAddr = 0x29;
dev.i2c_fd = fd; dev.i2c_fd = fd;
VL53L0X_Error Status = VL53L0X_DataInit(&dev); VL53L0X_Error Status = VL53L0X_DataInit(&dev);
if (Status != VL53L0X_ERROR_NONE) { if (Status != VL53L0X_ERROR_NONE) {
fprintf(stderr, "[VL53L0X] DataInit failed: %d\n", Status); fprintf(stderr, "[VL53L0X] DataInit failed: %d\n", Status);
close(fd); close(fd);
fd = -1; fd = -1;
return false; return false;
} }
Status = VL53L0X_StaticInit(&dev); Status = VL53L0X_StaticInit(&dev);
if (Status != VL53L0X_ERROR_NONE) { if (Status != VL53L0X_ERROR_NONE) {
fprintf(stderr, "[VL53L0X] StaticInit failed: %d\n", Status); fprintf(stderr, "[VL53L0X] StaticInit failed: %d\n", Status);
close(fd); close(fd);
fd = -1; fd = -1;
return false; return false;
} }
uint32_t refSpadCount; uint32_t refSpadCount;
uint8_t isApertureSpads; uint8_t isApertureSpads;
uint8_t VhvSettings; uint8_t VhvSettings;
uint8_t PhaseCal; uint8_t PhaseCal;
VL53L0X_PerformRefCalibration(&dev, &VhvSettings, &PhaseCal); VL53L0X_PerformRefCalibration(&dev, &VhvSettings, &PhaseCal);
VL53L0X_PerformRefSpadManagement(&dev, &refSpadCount, &isApertureSpads); VL53L0X_PerformRefSpadManagement(&dev, &refSpadCount, &isApertureSpads);
Status = VL53L0X_SetDeviceMode(&dev, VL53L0X_DEVICEMODE_SINGLE_RANGING); Status = VL53L0X_SetDeviceMode(&dev, VL53L0X_DEVICEMODE_SINGLE_RANGING);
if (Status != VL53L0X_ERROR_NONE) { if (Status != VL53L0X_ERROR_NONE) {
fprintf(stderr, "[VL53L0X] SetDeviceMode failed: %d\n", Status); fprintf(stderr, "[VL53L0X] SetDeviceMode failed: %d\n", Status);
close(fd); close(fd);
fd = -1; fd = -1;
return false; return false;
} }
VL53L0X_SetMeasurementTimingBudgetMicroSeconds(&dev, 20000); VL53L0X_SetMeasurementTimingBudgetMicroSeconds(&dev, 20000);
uint32_t actualBudget = 0; uint32_t actualBudget = 0;
VL53L0X_GetMeasurementTimingBudgetMicroSeconds(&dev, &actualBudget); VL53L0X_GetMeasurementTimingBudgetMicroSeconds(&dev, &actualBudget);
fprintf(stderr, "[VL53L0X] timing budget = %u us\n", actualBudget); fprintf(stderr, "[VL53L0X] timing budget = %u us\n", actualBudget);
initialized = true; initialized = true;
fprintf(stderr, "[VL53L0X] init OK\n"); fprintf(stderr, "[VL53L0X] init OK\n");
return true; return true;
} }
bool VL53L0X::readRange(VL53L0X_RangingMeasurementData_t &data) bool VL53L0X::readRange(VL53L0X_RangingMeasurementData_t &data)
{ {
if (!initialized) return false; if (!initialized) return false;
VL53L0X_Error Status; VL53L0X_Error Status;
VL53L0X_ClearInterruptMask(&dev, 0); VL53L0X_ClearInterruptMask(&dev, 0);
Status = VL53L0X_StartMeasurement(&dev); Status = VL53L0X_StartMeasurement(&dev);
if (Status != VL53L0X_ERROR_NONE) { if (Status != VL53L0X_ERROR_NONE) {
fprintf(stderr, "[VL53L0X] StartMeasurement failed: %d\n", Status); fprintf(stderr, "[VL53L0X] StartMeasurement failed: %d\n", Status);
return false; return false;
} }
uint8_t ready = 0; uint8_t ready = 0;
int timeout = 500; int timeout = 500;
while (!ready && --timeout > 0) { while (!ready && --timeout > 0) {
Status = VL53L0X_GetMeasurementDataReady(&dev, &ready); Status = VL53L0X_GetMeasurementDataReady(&dev, &ready);
if (Status != VL53L0X_ERROR_NONE) if (Status != VL53L0X_ERROR_NONE)
break; break;
if (!ready) if (!ready)
usleep(1000); usleep(1000);
} }
if (!ready) { if (!ready) {
fprintf(stderr, "[VL53L0X] measurement timeout\n"); fprintf(stderr, "[VL53L0X] measurement timeout\n");
return false; return false;
} }
Status = VL53L0X_GetRangingMeasurementData(&dev, &data); Status = VL53L0X_GetRangingMeasurementData(&dev, &data);
if (Status != VL53L0X_ERROR_NONE) { if (Status != VL53L0X_ERROR_NONE) {
fprintf(stderr, "[VL53L0X] GetRangingMeasurementData failed: %d\n", Status); fprintf(stderr, "[VL53L0X] GetRangingMeasurementData failed: %d\n", Status);
return false; return false;
} }
VL53L0X_ClearInterruptMask(&dev, 0); VL53L0X_ClearInterruptMask(&dev, 0);
return true; return true;
} }
bool VL53L0X::startMeasure() bool VL53L0X::startMeasure()
{ {
if (!initialized) return false; if (!initialized) return false;
VL53L0X_ClearInterruptMask(&dev, 0); VL53L0X_ClearInterruptMask(&dev, 0);
VL53L0X_Error Status = VL53L0X_StartMeasurement(&dev); VL53L0X_Error Status = VL53L0X_StartMeasurement(&dev);
return (Status == VL53L0X_ERROR_NONE); return (Status == VL53L0X_ERROR_NONE);
} }
bool VL53L0X::readResult(VL53L0X_RangingMeasurementData_t &data) bool VL53L0X::readResult(VL53L0X_RangingMeasurementData_t &data)
{ {
if (!initialized) return false; if (!initialized) return false;
uint8_t ready = 0; uint8_t ready = 0;
VL53L0X_Error Status; VL53L0X_Error Status;
int timeout = 25; // 25ms max, 读不到就跳过 int timeout = 25; // 25ms max, 读不到就跳过
while (!ready && --timeout > 0) { while (!ready && --timeout > 0) {
Status = VL53L0X_GetMeasurementDataReady(&dev, &ready); Status = VL53L0X_GetMeasurementDataReady(&dev, &ready);
if (Status != VL53L0X_ERROR_NONE) if (Status != VL53L0X_ERROR_NONE)
return false; return false;
if (!ready) if (!ready)
usleep(1000); usleep(1000);
} }
if (!ready) return false; if (!ready) return false;
Status = VL53L0X_GetRangingMeasurementData(&dev, &data); Status = VL53L0X_GetRangingMeasurementData(&dev, &data);
VL53L0X_ClearInterruptMask(&dev, 0); VL53L0X_ClearInterruptMask(&dev, 0);
return (Status == VL53L0X_ERROR_NONE); return (Status == VL53L0X_ERROR_NONE);
} }
bool VL53L0X::stop() bool VL53L0X::stop()
{ {
if (fd >= 0) { if (fd >= 0) {
close(fd); close(fd);
fd = -1; fd = -1;
} }
initialized = false; initialized = false;
return true; return true;
} }
-312
View File
@@ -1,312 +0,0 @@
/*
* zebra_detect.cpp — 斑马线检测实现
* 算法对齐 gd13.py: 透视变换 → 白色掩码 → Sobel 梯度 → 滑窗判定
*/
#define ZEBRA_DEBUG 1
#include "zebra_detect.h"
#include <cmath>
#include <cstdio>
using namespace cv;
using namespace std;
#if ZEBRA_DEBUG
#define ZLOG(fmt, ...) fprintf(stderr, "[zebra] " fmt "\n", ##__VA_ARGS__)
#else
#define ZLOG(fmt, ...) ((void)0)
#endif
// ============================================================
// 参数 (对齐 gd13.py)
// ============================================================
static const int PROC_SIZE = 400;
static const int WIN_H = 120;
static const int WIN_W = 300;
static const int WIN_STEP = 20;
static const float AMP_THRESH = 12.0f;
static const int COUNT_THRESH = 150;
static const float MIN_VRATIO = 0.45f;
static const int MIN_VPIXELS = 300;
// ============================================================
// 透视变换矩阵
// ============================================================
static Mat get_birdview_transform()
{
vector<Point2f> src = {
{30.f, 380.f},
{370.f, 380.f},
{320.f, 180.f},
{80.f, 180.f}
};
vector<Point2f> dst = {
{50.f, 350.f},
{350.f, 350.f},
{350.f, 50.f},
{50.f, 50.f}
};
return getPerspectiveTransform(src, dst);
}
// ============================================================
// 白色掩码 (HSV)
// ============================================================
static Mat get_white_zebra_mask(const Mat &bgr)
{
Mat hsv;
cvtColor(bgr, hsv, COLOR_BGR2HSV);
Mat white_mask;
inRange(hsv, Scalar(0, 0, 180), Scalar(180, 30, 255), white_mask);
ZLOG(" 白掩码 H:[0,180] S:[0,30] V:[180,255] 白色像素=%d", countNonZero(white_mask));
Mat brown_mask;
inRange(hsv, Scalar(10, 20, 80), Scalar(30, 100, 200), brown_mask);
ZLOG(" 棕掩码 H:[10,30] S:[20,100] V:[80,200] 棕色像素=%d", countNonZero(brown_mask));
Mat not_brown;
bitwise_not(brown_mask, not_brown);
bitwise_and(white_mask, not_brown, white_mask);
ZLOG(" 排除棕色后白色像素=%d", countNonZero(white_mask));
Mat kernel = getStructuringElement(MORPH_RECT, Size(2, 2));
morphologyEx(white_mask, white_mask, MORPH_OPEN, kernel, Point(-1,-1), 1);
morphologyEx(white_mask, white_mask, MORPH_CLOSE, kernel, Point(-1,-1), 1);
ZLOG(" 开闭运算后白色像素=%d", countNonZero(white_mask));
return white_mask;
}
// ============================================================
// 预处理
// ============================================================
static Mat preprocess(const Mat &bgr)
{
Mat white_mask = get_white_zebra_mask(bgr);
Mat gray;
cvtColor(bgr, gray, COLOR_BGR2GRAY);
bitwise_and(gray, gray, gray, white_mask);
medianBlur(gray, gray, 3);
Mat kernel1 = getStructuringElement(MORPH_RECT, Size(3, 3));
Mat kernel2 = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(gray, gray, MORPH_OPEN, kernel1, Point(-1,-1), 1);
morphologyEx(gray, gray, MORPH_CLOSE, kernel2, Point(-1,-1), 1);
return gray;
}
// ============================================================
// 梯度计算
// ============================================================
static void compute_gradient(const Mat &gray, Mat &amplitude, Mat &theta)
{
Mat sobelx, sobely;
Sobel(gray, sobelx, CV_32F, 1, 0, 3);
Sobel(gray, sobely, CV_32F, 0, 1, 3);
phase(sobelx, sobely, theta, true);
for (int r = 0; r < theta.rows; ++r)
for (int c = 0; c < theta.cols; ++c)
theta.at<float>(r, c) = fmod(theta.at<float>(r, c), 180.f);
magnitude(sobelx, sobely, amplitude);
// 统计过滤前
int before = countNonZero(amplitude);
for (int r = 0; r < amplitude.rows; ++r)
for (int c = 0; c < amplitude.cols; ++c)
if (amplitude.at<float>(r, c) < 10.f)
amplitude.at<float>(r, c) = 0.f;
int after = countNonZero(amplitude);
double amp_min, amp_max;
minMaxLoc(amplitude, &amp_min, &amp_max);
ZLOG(" 梯度: 过滤前=%d, 过滤后(amp>10)=%d, 幅值范围=[%.1f, %.1f]",
before, after, amp_min, amp_max);
}
// ============================================================
// 单窗口判定 (无 vector 分配, 避免 OOM)
// ============================================================
static bool is_zebra_window(const Mat &amp_win, const Mat &ang_win, int win_top)
{
ZLOG("--- 窗口 top=%d [%dx%d] ---", win_top, amp_win.cols, amp_win.rows);
int total = 0; // amplitude > AMP_THRESH 的像素总数
int hist[4] = {0}; // 水平边缘直方图 [80-85,85-90,90-95,95-100)
int v_count = 0; // 垂直边缘计数 [0-10][170-180]
// 单次遍历: 同时统计 total, hist, v_count
for (int r = 0; r < amp_win.rows; ++r)
{
for (int c = 0; c < amp_win.cols; ++c)
{
float amp = amp_win.at<float>(r, c);
if (amp <= AMP_THRESH)
continue;
++total;
float a = ang_win.at<float>(r, c);
if (a >= 80.f && a < 100.f)
{
int bin = (int)(a - 80.f) / 5;
if (bin >= 0 && bin < 4)
hist[bin]++;
}
if (a <= 10.f || a >= 170.f)
++v_count;
}
}
ZLOG(" 梯度像素(amplitude>%.0f)=%d", AMP_THRESH, total);
if (total == 0)
{
ZLOG(" -> 丢弃: 无有效梯度像素");
return false;
}
// 找峰值 bin
int peak = 0, peak_bin = 0;
for (int i = 0; i < 4; ++i)
if (hist[i] > peak) { peak = hist[i]; peak_bin = i; }
// 二次遍历: 统计峰值方向的像素数 (需要知道具体区间)
int h_count = 0;
float low_a = 80.f + peak_bin * 5.f;
float high_a = low_a + 5.f;
for (int r = 0; r < amp_win.rows; ++r)
{
for (int c = 0; c < amp_win.cols; ++c)
{
if (amp_win.at<float>(r, c) <= AMP_THRESH)
continue;
float a = ang_win.at<float>(r, c);
if (a >= low_a && a <= high_a)
++h_count;
}
}
ZLOG(" 水平边缘[80-100): hist=[%d,%d,%d,%d], 峰值bin=%d(%.0f-%.0f度), "
"峰值像素=%d, 阈值=%d",
hist[0], hist[1], hist[2], hist[3],
peak_bin, low_a, high_a, h_count, COUNT_THRESH);
if (h_count < COUNT_THRESH)
{
ZLOG(" -> 丢弃: 水平边缘像素不足 (%d < %d)", h_count, COUNT_THRESH);
return false;
}
float v_ratio = (float)v_count / (float)(total + 1e-6);
ZLOG(" 垂直边缘[0-10|170-180]: 像素=%d, 占比=%.3f, 要求: >=%d && 占比>=%.2f",
v_count, v_ratio, MIN_VPIXELS, MIN_VRATIO);
if (v_count < MIN_VPIXELS)
{
ZLOG(" -> 丢弃: 垂直像素不足 (%d < %d)", v_count, MIN_VPIXELS);
return false;
}
if (v_ratio < MIN_VRATIO)
{
ZLOG(" -> 丢弃: 垂直占比不足 (%.3f < %.2f)", v_ratio, MIN_VRATIO);
return false;
}
ZLOG(" -> 判定: 斑马线窗口!");
return true;
}
// ============================================================
// detect_zebra_crossing — 主检测函数
// ============================================================
ZebraResult detect_zebra_crossing(const Mat &bgr_frame)
{
ZebraResult result;
result.detected = false;
result.distance_px = -1;
ZLOG("========================================");
ZLOG("新帧开始: 输入尺寸=%dx%d", bgr_frame.cols, bgr_frame.rows);
if (bgr_frame.empty())
{
ZLOG("错误: 输入帧为空");
return result;
}
static Mat M = get_birdview_transform();
static Mat proc, birdview, roi, gray, amplitude, theta;
// 1. 缩放 → 透视变换 → 裁剪 ROI(顶部30px) → 恢复 400×400
resize(bgr_frame, proc, Size(PROC_SIZE, PROC_SIZE));
ZLOG("步骤1-缩放: %dx%d -> %dx%d", bgr_frame.cols, bgr_frame.rows,
PROC_SIZE, PROC_SIZE);
warpPerspective(proc, birdview, M, Size(PROC_SIZE, PROC_SIZE));
roi = birdview(Rect(0, 30, PROC_SIZE, PROC_SIZE - 30));
resize(roi, proc, Size(PROC_SIZE, PROC_SIZE));
ZLOG("步骤1-透视+ROI: 裁剪顶部30px, 鸟瞰输出=%dx%d", proc.cols, proc.rows);
// 2. 预处理 + 梯度
ZLOG("步骤2-预处理开始");
gray = preprocess(proc);
ZLOG("步骤2-预处理完成, 灰度非零像素=%d", countNonZero(gray));
ZLOG("步骤3-梯度计算开始");
compute_gradient(gray, amplitude, theta);
int amp_nz = countNonZero(amplitude);
ZLOG("步骤3-梯度完成, 总非零梯度像素=%d", amp_nz);
if (amp_nz == 0)
{
ZLOG("结果: 无梯度 → 未检测到斑马线");
return result;
}
// 3. 滑动窗口
ZLOG("步骤4-滑动窗口: 窗口=%dx%d, 步长=%d, 遍历范围=[0,%d]",
WIN_W, WIN_H, WIN_STEP, proc.rows - WIN_H);
int z_ymin = proc.rows;
int z_ymax = 0;
int valid = 0;
int total_wins = 0;
for (int top = 0; top <= proc.rows - WIN_H; top += WIN_STEP)
{
++total_wins;
Rect win(0, top, WIN_W, WIN_H);
if (is_zebra_window(amplitude(win), theta(win), top))
{
++valid;
if (top < z_ymin) z_ymin = top;
if (top + WIN_H > z_ymax) z_ymax = top + WIN_H;
}
}
// 4. 判定
int span = z_ymax - z_ymin;
ZLOG("步骤5-汇总: 总窗口=%d, 有效=%d, "
"斑马线区域: top=%d~%d, 跨度=%d, 判定阈值=%d",
total_wins, valid, z_ymin, z_ymax, span, WIN_H);
if (span > WIN_H)
{
result.detected = true;
result.distance_px = PROC_SIZE - z_ymax;
ZLOG("结果: 检测到斑马线! 下沿距底部=%dpx (ymax=%d)",
result.distance_px, z_ymax);
}
else
{
ZLOG("结果: 未检测到斑马线 (跨度%d <= 阈值%d)", span, WIN_H);
}
return result;
}
Binary file not shown.
+123
View File
@@ -0,0 +1,123 @@
"""
Mild Mega r2 → mild_v13.bin 导出
架构: 3→9→9→13→13→19→19→19→44→44→64→64 → head(dw,64→64) → out(64→9)
无残差连接, 纯顺序 conv_bn_relu + SE
"""
import sys, struct, os
import torch
import torch.nn as nn
import numpy as np
class MildMegaR2(nn.Module):
def __init__(self, num_classes=4):
super().__init__()
channels = [3, 9, 9, 13, 13, 19, 19, 19, 44, 44, 64, 64]
strides = [2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1]
for i in range(11):
in_c, out_c, s = channels[i], channels[i + 1], strides[i]
if s == 2:
conv = nn.Conv2d(in_c, out_c, 3, s, 1, bias=False)
elif in_c == out_c:
conv = nn.Conv2d(in_c, out_c, 3, 1, 1, groups=in_c, bias=False)
else:
conv = nn.Conv2d(in_c, out_c, 1, 1, 0, bias=False)
setattr(self, f'b{i + 1}', nn.Sequential(
conv,
nn.BatchNorm2d(out_c),
nn.ReLU(inplace=True),
))
mid = out_c // 2
setattr(self, f'se_{i}', nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Conv2d(out_c, mid, 1, bias=True),
nn.ReLU(inplace=True),
nn.Conv2d(mid, out_c, 1, bias=True),
nn.Sigmoid(),
))
# head: depthwise 3x3, 64→64
self.head = nn.Sequential(
nn.Conv2d(64, 64, 3, 1, 1, groups=64, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
)
# output: 1x1 conv, 64→(4 class + 1 bg + 4 bbox) = 9
self.out = nn.Conv2d(64, 9, 1, bias=True)
def forward(self, x):
for i in range(11):
x = getattr(self, f'b{i + 1}')(x)
se_out = getattr(self, f'se_{i}')(x)
x = x * se_out
x = self.head(x)
x = self.out(x)
return x
def export(pth_path, bin_path):
model = MildMegaR2(num_classes=4)
ckpt = torch.load(pth_path, map_location='cpu', weights_only=False)
# Handle wrapped checkpoint
if isinstance(ckpt, dict) and 'model' in ckpt:
ckpt = ckpt['model']
if isinstance(ckpt, dict) and 'state_dict' in ckpt:
ckpt = ckpt['state_dict']
# Remove 'module.' prefix (from DataParallel/DDP)
cleaned = {}
for k, v in ckpt.items():
nk = k.replace('module.', '')
cleaned[nk] = v
model.load_state_dict(cleaned, strict=False)
model.eval()
params = {}
for name, param in model.named_parameters():
params[name] = param.detach().cpu().numpy().astype(np.float32)
for name, buf in model.named_buffers():
params[name] = buf.detach().cpu().numpy().astype(np.float32)
total = sum(v.size for v in params.values())
print(f"Layers: {len(params)}, params: {total:,}{total / 1000:.1f}K")
for k, v in sorted(params.items()):
sh = str(list(v.shape))
print(f" {k:50s} {sh:25s} {v.size:,}")
with open(bin_path, 'wb') as f:
f.write(struct.pack('i', len(params)))
for name in sorted(params.keys()):
arr = params[name]
nb = name.encode('utf-8')
f.write(struct.pack('i', len(nb)))
f.write(nb)
f.write(struct.pack('i', arr.ndim))
for d in arr.shape:
f.write(struct.pack('i', d))
f.write(arr.tobytes())
size_kb = os.path.getsize(bin_path) / 1024
print(f"\nExported: {bin_path} ({size_kb:.0f} KB)")
# Quick inference test
x = torch.randn(1, 3, 120, 160)
with torch.no_grad():
y = model(x)
print(f"Input: {list(x.shape)} → Output: {list(y.shape)} (OK)")
return True
if __name__ == '__main__':
import os
os.chdir(os.path.dirname(os.path.abspath(__file__)))
pth = 'best_v13_mild_r2.pth'
if not os.path.exists(pth):
print(f"ERROR: {pth} not found")
sys.exit(1)
export(pth, 'mild_v13.bin')
+18
View File
@@ -0,0 +1,18 @@
import torch, sys, os
os.chdir(os.path.dirname(os.path.abspath(__file__)))
pth = 'best_v13_mild_r2.pth'
ckpt = torch.load(pth, map_location='cpu', weights_only=False)
print(f"Type: {type(ckpt).__name__}")
if isinstance(ckpt, dict):
if 'model' in ckpt:
print("Has 'model' key")
ckpt = ckpt['model']
if 'state_dict' in ckpt:
print("Has 'state_dict' key")
ckpt = ckpt['state_dict']
print(f"\nTotal keys: {len(ckpt)}")
for k, v in sorted(ckpt.items()):
shape = tuple(v.shape) if hasattr(v, 'shape') else 'scalar'
print(f" {k:50s} {str(shape)}")
else:
print("Not a dict, top-level keys unknown")