Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f96df39d4 | |||
| 0502948bcd | |||
| cbb54b4882 | |||
| 66fb213861 | |||
| 97e06314cc | |||
| ad48c955d9 | |||
| b69a5ff5bc | |||
| a43ff769d4 | |||
| afc839e8cb | |||
| 08b00d6c97 | |||
| b9141eaf8a | |||
| e720009794 | |||
| 8ee66fe444 | |||
| 7b220f5c3b | |||
| 7284a8d037 | |||
| 54f13984a9 | |||
| 670f84131b |
+9
-5
@@ -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/
|
||||||
|
|||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"python-envs.defaultEnvManager": "ms-python.python:conda",
|
|
||||||
"python-envs.defaultPackageManager": "ms-python.python:conda"
|
|
||||||
}
|
|
||||||
+1
-1
@@ -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
@@ -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
@@ -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)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# 比赛参数固化
|
||||||
|
|
||||||
|
> 截至 2026-07-04,16速,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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+257
-257
@@ -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_ */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 &litude, 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, &_min, &_max);
|
|
||||||
ZLOG(" 梯度: 过滤前=%d, 过滤后(amp>10)=%d, 幅值范围=[%.1f, %.1f]",
|
|
||||||
before, after, amp_min, amp_max);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// 单窗口判定 (无 vector 分配, 避免 OOM)
|
|
||||||
// ============================================================
|
|
||||||
static bool is_zebra_window(const Mat &_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.
@@ -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')
|
||||||
@@ -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")
|
||||||
Reference in New Issue
Block a user