Files

6.0 KiB
Raw Permalink Blame History

AGENTS.md — SmartCar Demo

Project overview

龙芯 2K0300 嵌入式自动驾驶智能车,OpenCV + Mild v12 魔改 YOLO 模型。 板端运行,x86 Linux 交叉编译。No unit tests, no CI, no linting — tested on-device only.

Build

# On the build host (x86 Linux/WSL):
mkdir build && cd build
cmake ..
make -j$(nproc)
  • Cross-compilation target: LoongArch64 (-march=loongarch64 -mtune=loongarch64)
  • Toolchain: /opt/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.6
  • C++ standard: 17
  • OpenCV path (WSL): /home/ilikara/loongson/opencv-4.13.0/loongson (v4.13.0, 无 SIMD)
  • OpenCV 设备库: opencv_libs/ 目录下 .so.413 文件,部署到设备 /home/root/opencv/lib/ 并更新 .so 符号链接
  • cross.cmake is included before cmake_minimum_required — intentional, to set compiler before project().
  • Set CROSS_COMPILE to 0 in cross.cmake for native x86 builds.

Project structure

Directory Purpose
src/ Source (.cpp + .hpp) → compiled into common_lib (static lib)
lib/ Public headers (.h only) + vl53l0x/ C API sources
main/ Entry points → smartcar_demo1 (main) + lidar_test (standalone test)
docs/ Design docs (ARCHITECTURE, CONE_DESIGN, ENCODER_BRAKE, LIDAR_AVOID, TRAFFIC_LIGHT)
build/ CMake build output (gitignored)

Executable name: smartcar_demo1 (CMake project name is smartcar_demo2 — mismatch is intentional).

Excluded modules

These source files exist in src/ but are excluded from build via CMakeLists.txt FILTER EXCLUDE:

  • zebra_detect.cpp — classic zebra-crossing detection (replaced by Mild model)
  • PIDController.cpp — unused (motor is open-loop direct drive)
  • serial.cpp — Vofa/serial image streaming, unused

Note: vl53l0x.cpp IS compiled (lidar ranging is active).

Device-side operation

Controlled via ctl.sh (writes to text files, no CLI args):

# On device:
sh ctl.sh init          # initialize GPIO/PWM pins + write default config files
sh ctl.sh start         # init_pins + start the demo in background
sh ctl.sh stop          # stop and zero PWM

ctl.sh writes default config values to text files (./speed, ./steer_gain, etc.). The binary reads them at startup via cfg_load_all() and re-reads every 30 frames when ./debug = 1.

Bug: start.sh references binary as smartcar_demo but actual executable is smartcar_demo1 — use ctl.sh instead.

Configuration system

All config is via single-value text files in the working directory. The full list of parameters and defaults is in lib/global.h (struct CfgCache). Config is loaded by cfg_load_all() in src/global.cpp.

Key groups:

  • Steering: speed, deadband, steer_gain, center_bias, foresee
  • Debug: start (0/1), showImg (0/1), debug (0/1), destfps, saveImg
  • Zebra: zebrasee
  • Cone avoidance: cone_avoid_gain, cone_avoid_range, cone_speed, cone_min_frames, cone_margin, cone_thresh, cone_hold_frames, cone_return_gain, cone_return_frames
  • Curve slowdown: curve_slope (default 0.4), curve_min (default 0.8)
  • Encoder brake: brake_scale, brake_max
  • Lidar avoidance: lidar_enable, lidar_thresh, lidar_pre, lidar_near, lidar_far, lidar_near_start, lidar_near_end, lidar_far_span, lidar_min_frames, lidar_avoid_gain, lidar_avoid_range, lidar_speed, lidar_hold_frames

Architecture

Per-frame pipeline in CameraHandler() (src/camera.cpp:755)

CameraHandler()
├── capture_frame()           // 1. MJPG 取帧 → 1/4解码 320×240 BGR
├── save_image_if_requested() // 2. 保存帧 (debug)
├── image_main()              // 3. 视觉巡线 (80×60 HSV-Otsu-FloodFill)
├── lidar_avoid_process()     // 4. VL53L0X 激光避障 (每2帧) + 中线变形
├── run_model_inference()     // 5. Mild v12 每2帧推理 (160×120, 4类)
├── zebra_process()           // 6a. 斑马线去抖 + Z_STOP/Z_COOLDOWN
├── traffic_light_process()   // 6b. 红绿灯 TL_NORMAL→TL_STOP→TL_WAIT_GREEN
├── cone_detect_and_deform()  // 6c. 锥桶检测 + 中线变形 + 保持衰减
├── steering_update()         // 7. 舵机比例控制 (deadband过滤)
├── motor_update()            // 8. 电机开环PWM + 编码器刹车 + 弯道减速
├── lcd_render()              // 9. LCD RGB565渲染 (边界线+检测框+状态)
└── fps_log()                 // 10. 分步耗时日志

Also: malloc_trim(0) every 150 frames to return freed memory to OS (embedded optimization).

Motor control

  • Open-loop: MotorController::updateduty(spd) — direct PWM, no encoder feedback in normal driving.
  • Encoder brake: When zebra_block || tl_block, reads g_enc_speed from encoder thread and applies reverse braking.
  • Encoder thread (control.cpp): polls GPIO67 (pulse) + GPIO72 (direction), 100ms window → g_enc_speed (pulses/sec). 500µs sleep to prevent CPU starvation.
  • Curve slowdown: speed *= (1.0 - |deviation| × curve_slope), clamped to ≥ curve_min.
  • Cone/lidar speed reduction: Code exists but is currently commented out in motor_update().

Model: Mild v12

  • Input: 160×120 BGR, Output: 4 classes + background
  • Class indices: 0=cone, 1=red light, 2=green light, 3=zebra
  • Per-class thresholds: {0.65, 0.75, 0.80, 0.82} (cone/red/green/zebra)
  • Weight file: mild_v12.bin (105KB custom binary format)
  • Inference engine: src/model_v10.{hpp,cpp} (file names say v10, internally Mild v3 — historical naming)

Style and conventions

  • No copyright headers — comments use ascii-box-style block dividers
  • Header guards: #ifndef FILENAME_H_ / #define FILENAME_H_ (some model files use #pragma once)
  • Global state via extern globals (e.g., g_cfg, g_steer_deviation, g_boxes)
  • lib/ has .h headers; src/ has .cpp implementations + .hpp model headers
  • No unit tests, no CI, no linting — do not add comments to code unless asked