Files
Loongson_2k0300_SmartCar/AGENTS.md
T

3.8 KiB
Raw Blame History

AGENTS.md — SmartCar Demo

Project overview

LoongArch64 embedded autonomous smart car using OpenCV + NanoDet V10 model. Runs on-device (Loongson board) with cross-compilation from x86 Linux.

Build

# On the build host (x86 Linux):
mkdir build && cd build
cmake ..
make
  • Cross-compilation target: LoongArch64 (-march=loongarch64)
  • Toolchain: /opt/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.6
  • C++ standard: 17
  • OpenCV path (device-side): /mnt/d/PPPProgram/smartcar/opencv_device/
  • cross.cmake is included before cmake_minimum_required — this is intentional.

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 (the CMake project name smartcar_demo2 is different — don't assume they match).

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 NanoDet model
  • encoder.cpp — referenced in exclusion list but file does not exist in repo

Device-side operation

The onboard binary is controlled via text files in the working directory — no CLI args.

# On device:
sh ctl.sh init          # initialize GPIO/PWM pins
sh ctl.sh start         # start the demo
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. start.sh uses LD_PRELOAD=./gpio_fix_final.so (GPIO workaround).

Configuration system

All config is via single-value text files in the working directory:

  • ./speed (double) — target speed
  • ./start (0/1) — motor enable switch
  • ./debug (0/1) — when 1, reloads all config files every 7 frames
  • ./showImg (0/1) — LCD display toggle
  • ./deadband, ./steer_gain, ./center_bias — steering tuning
  • ./foresee — look-ahead row for steering
  • ./zebrasee — zebra crossing near-threshold
  • ./destfps — target framerate
  • ./kp, ./ki, ./kd — PID gains (currently not used; motor is open-loop)
  • ./mortor_kp, ./mortor_ki, ./mortor_kd — motor encoder PID (spelling mortor is intentional)

Architecture

9-step per-frame pipeline in CameraHandler() (src/camera.cpp):

  1. Capture frame (640×480 MJPEG → BGR)
  2. Optionally save image
  3. Vision line tracking (80×60 downscale → HSV+Otsu → floodFill → mid_line[60])
  4. Model inference every 2nd frame (NanoDet V10, 4 classes: cone/red/green/zebra)
  5. Zebra crossing state machine (NORMAL→STOP(4s)→COOLDOWN(5s))
  6. Steering servo control (PWM, deadband-filtered)
  7. Motor control (open-loop duty cycle, curve-based slowdown in turns)
  8. LCD rendering (/dev/fb0 mmap)
  9. FPS logging

Key detail: Motor control is open-loopMotorController::updateSpeed() and encoder PID exist in code but are never called from the main loop. Only updateduty() (direct PWM) is used.

Currently cones (cls=0), red lights (cls=1), and green lights (cls=2) are detected by the model but ignored in decision logic.

Style and conventions

  • C++ files have no copyright headers and minimal comments — comments are ascii-box-style block comments when present
  • Header guards use the form #ifndef FILENAME_H_ / #define FILENAME_H_
  • 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