# AGENTS.md — SmartCar Demo ## Project overview 龙芯 2K0300 嵌入式自动驾驶智能车,OpenCV + Mild v12 魔改 YOLO 模型。 板端运行,x86 Linux 交叉编译。 ## Build ```sh # 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** (device-side): `D:\PPPProgram\smartcar\opencv_device\` (mounted as `/mnt/d/...` in WSL) - `cross.cmake` is included **before** `cmake_minimum_required` — intentional, to set compiler before project(). ## Project structure | Directory | Purpose | |-----------|---------| | `src/` | Source → compiled into `common_lib` (static lib) | | `lib/` | Public headers only (no .cpp) | | `main/` | Entry point → executable `smartcar_demo1` | | `docs/` | Architecture docs (`ARCHITECTURE.md` is the design reference) | | `build/` | CMake build output (gitignored) | **Executable name**: `smartcar_demo1` (CMake project name `smartcar_demo2` ≠ executable name). ## Excluded modules These source files exist but are **excluded from build**: - `vl53l0x.cpp` — laser ranging module, hardware not connected - `zebra_detect.cpp` — classic zebra-crossing detection (replaced by Mild model) ## Device-side operation Controlled via `ctl.sh` (writes to text files, no CLI args): ```sh # On device: sh ctl.sh init # initialize GPIO/PWM pins + write default config files sh ctl.sh start # start the demo in background sh ctl.sh stop # stop and zero PWM ``` `ctl.sh` sets default config values by writing to files like `./speed`, `./kp`, `./steer_gain`, etc. The running binary reads these files at startup and optionally re-reads them every 7 frames (when `./debug` = 1). `start.sh` is an alternative launcher using `LD_PRELOAD=./gpio_fix_final.so` for the GPIO 74 workaround. ## Configuration system All config is via single-value text files in the working directory: ### Steering - `./speed` (double) — target speed (duty cycle %) - `./deadband` — steering deadband (pixels) - `./steer_gain` — steering gain multiplier - `./center_bias` — midline offset correction - `./foresee` — look-ahead row for steering ### Debug / Display - `./start` (0/1) — motor enable switch - `./showImg` (0/1) — LCD display toggle - `./debug` (0/1) — when 1, reloads all config files every 7 frames - `./destfps` — target framerate - `./saveImg` — when written as 1 (in debug mode), saves current frame ### Zebra crossing - `./zebrasee` — zebra crossing near-threshold (cy > this = near) ### Cone avoidance - `./cone_avoid_gain` — midline deformation push amount (normalized) - `./cone_avoid_range` — deformation ramp steepness - `./cone_speed` — speed multiplier when cone triggered - `./cone_min_frames` — consecutive confirmation frames - `./cone_margin` — 0=center point, 1=box edge - `./cone_thresh` — confidence threshold - `./cone_hold_frames` — hold deformation frames after cone disappears ### Encoder brake - `./brake_scale` — speed (pps) → brake duty cycle (ns) scaling factor - `./brake_max` — maximum brake duty cycle (ns) ### PID gains (reserved, motor is open-loop) - `./kp`, `./ki`, `./kd` — steering PID (currently not used) - `./mortor_kp`, `./mortor_ki`, `./mortor_kd` — motor encoder PID (note: spelling `mortor` is intentional) ## Architecture ### Per-frame pipeline in `CameraHandler()` ([`src/camera.cpp`](file:///D:\PPPProgram\smartcar\smartcar2\src\camera.cpp)) 1. **Capture frame** — 640×480 MJPEG → `cv::imdecode(IMREAD_REDUCED_COLOR_4)` → 1/4 decode to 320×240 BGR 2. **Save image** (debug mode only, when `./saveImg` = 1) 3. **Vision line tracking** — resize to 80×60 → HSV dual-channel Otsu → floodFill → longest-run search → `left_line[60]`, `right_line[60]`, `mid_line[60]` 4. **Model inference** — every 2nd frame, Mild v12 model at 160×120, 4 classes: cone(0) / red light(1) / green light(2) / zebra(3) 5. **Zebra state machine** — NORMAL → STOP(4s) → COOLDOWN(5s) → NORMAL, with debounce (5 frames min, far-enough cy check) 6. **Traffic light state machine** — TL_NORMAL → TL_STOP (red≥3 frames) → TL_WAIT_GREEN (red gone) → TL_NORMAL (green≥3 frames) 7. **Cone avoidance** — confirmed cone detection deforms midline to steer away, with hold-frames decay after cone disappears 8. **Steering servo** — deadband-filtered proportional control via PWM 9. **Motor control** — open-loop duty cycle with curve slowdown in turns; encoder brake on zebra/red-light stop 10. **LCD rendering** — `/dev/fb0` mmap, RGB565 conversion, bounding boxes + state indicator overlay 11. **FPS logging** — every 15 frames, prints per-stage timing ### Motor control details - **Open-loop**: `MotorController::updateduty(spd)` — direct PWM duty cycle, no encoder feedback in normal driving. - **Encoder brake**: When `zebra_block=true` (red light or zebra stop), reads `g_enc_speed` from the encoder thread and applies reverse braking proportional to current speed. - **Encoder thread** ([`control.cpp:32`](file:///D:\PPPProgram\smartcar\smartcar2\src\control.cpp#L32)): polls GPIO67 (LSB pulse) + GPIO72 (direction) at ~2kHz, 100ms window speed calculation → `g_enc_speed` (pulses/sec). Now includes 500µs sleep to prevent CPU starvation. - **Curve slowdown**: `speed *= (1.0 - |deviation| × 0.4)`, clamped to ≥ 60%. ### Model: Mild v12 - **Architecture**: 3→9→9→13→13→19→19→19→44→44→64→64 → head(64→64,dw) → out(64→9) - **Input**: 160×120 BGR - **Output**: 4 classes (cone / red light / green light / zebra) + background - **Classes used in decision logic**: - cls=0 (cone) → midline deformation avoidance - cls=1 (red light) → traffic light state machine stop - cls=2 (green light) → traffic light state machine resume - cls=3 (zebra) → zebra crossing state machine stop - **Per-class thresholds**: `{0.90, 0.75, 0.80, 0.90}` (cone/red/green/zebra) - **Weight file**: `mild_v12.bin` (105KB custom binary format) - **Inference engine**: `src/model_v10.{hpp,cpp}` (names kept as `model_v10_*` for compatibility, internally Mild v3) ### Vision pipeline details - Processing resolution: 80×60 (optimal balance for 2K0300 CPU) - HSV dual-channel Otsu: H channel (blue hue) + S channel (saturation) → bitwise AND → track region - FloodFill: seed at bottom center (40, 50), 8-connected, extracts connected track - Per-row longest-run search on floodFill result → left/right boundaries - Missing-line recovery: propagate downward midline + virtual boundaries ## Style and conventions - C++ files have **no copyright headers** — comments are ascii-box-style block comments when present - Header guards use `#ifndef FILENAME_H_` / `#define FILENAME_H_` format (with some exceptions: `#pragma once` in model files) - Global state uses `extern` globals (e.g., `g_cfg`, `g_steer_deviation`, `g_boxes`) - `lib/` contains .h files only; `src/` contains .cpp files only - No unit tests, no CI, no linting — this is embedded code tested on-device