项目整体设计
car_project是龙芯2K0300智能车下位机工程主要包含摄像头巡线、LCD回显、双电机差速控制、编码器测速、MPU6050姿态反馈、VL53L0X测距、按键控制以及上位机遥测监视。创建工程目录zhengyangubuntu:~$ cd /opt/2k0300/loongson_2k300_lib/ zhengyangubuntu:/opt/2k0300/loongson_2k300_lib$ mkdir car_project当前car_project目录结构如下car_project/ ├── CMakeLists.txt # CMake 构建脚本 ├── README.md # 项目说明 ├── config.yaml # 全局配置文件 ├── main.cpp # 主程序入口 │ ├── app/ # 应用编排层 ├── drivers/ # 硬件驱动适配层 ├── tracking/ # 巡线算法模块 ├── core/ # 核心控制模块 ├── telemetry/ # 下位机遥测上传 ├── upper_monitor/ # Python 上位机监视工具 ├── utils/ # 日志、配置、滤波、几何工具 ├── test/ # 单元测试和硬件测试 ├── scripts/ # 构建、部署、运行脚本 └── tools/ # 预留工具目录几个主要目录的职责如下目录职责说明app/应用编排负责初始化硬件、启动线程、处理按键、注册任务和退出清理drivers/硬件驱动封装摄像头、LCD、IMU、测距、电机、编码器、按键tracking/巡线算法图像预处理、边界扫描、中线生成、道路识别、策略处理core/核心控制串级控制、传感器融合、周期调度telemetry/遥测上传通过UDP上传状态JSON和JPEG调试图upper_monitor/上位机接收下位机遥测显示图像和波形utils/公共工具日志、配置解析、滤波、巡线几何工具test/测试纯逻辑单元测试和硬件验证用例scripts/脚本本机编译、交叉编译、部署和远程运行1.1 程序运行流程main.cpp只保留最外层入口逻辑主要做4件事加载config.yaml初始化日志系统创建CarApplication启动应用并等待退出信号。真正的业务流程由app/CarApplication负责。这样做的好处是避免main.cpp越写越大后续维护时可以清楚地区分“程序入口”和“业务编排”。整体运行链路如下main.cpp └── CarApplication ├── 初始化配置、日志、控制器 ├── 初始化摄像头、LCD、IMU、编码器、测距、电机、按键 ├── 启动摄像头异步采集 ├── 启动 IMU / VL53L0X 连续读取 ├── 启动视觉、控制、编码器实时线程 ├── 周期执行 LCD 回显和遥测上传 └── 退出时停止电机并释放所有资源控制闭环的大致数据流如下摄像头图像 - tracking 巡线算法 - 得到巡线误差 tracking_error 和道路状态 road_state - controller 计算目标角速度和目标轮速 - data_fusion 提供 IMU yaw rate、编码器 RPS、测距状态 - controller 输出左右电机占空比 - motor_controller 控制左右电机1.2 配置文件config.yaml是整个工程的集中配置入口硬件路径、控制参数、巡线参数、调度周期、遥测参数都放在这里。配置加载由utils/config完成。配置模块只负责解析YAML并生成配置对象不直接访问硬件。常用配置包括camera: device: /dev/video0 width: 160 height: 120 fps: 60 mpu6050: enabled: true interval_ms: 20 vl53l0x: enabled: false key: enabled: false telemetry: enabled: false host: 192.168.1.100 state_port: 9000 image_port: 9001当前速度控制单位统一使用RPS也就是每秒转数。这样可以和编码器驱动、控制器、遥测字段保持一致避免在控制链路里反复进行RPM和RPS的换算。回到顶部二、主要模块说明2.1 应用编排模块appapp是下位机应用层核心类是CarApplication。2.1.1 源码路径car_application.hcar_application.cpphardware.cppkeys.cpprealtime.cpptasks.cpp2.1.2 主要功能CarApplication的主要职责初始化所有硬件驱动初始化巡线算法、控制器、数据融合和遥测模块启动摄像头异步采集启动控制线程、视觉线程、编码器线程注册LCD显示和遥测上传任务处理KEY0/KEY1按键业务程序退出时按顺序停止电机、线程和硬件资源。2.1.3 按键逻辑按键业务当前定义如下KEY0 短按 - 发车/暂停 KEY1 短按 - 速度档位切换 KEY1 长按 - 陀螺仪静态标定速度档位通过CascadeController::set_speed_scale()实现当前3档为gear 0 - 80% gear 1 - 100% gear 2 - 120%启用按键后默认从gear 0启动每次短按KEY1切换到下一档。2.2 工具模块utilsutils目录放置与具体硬件无关的公共工具。2.2.1log日志模块源码路径log.hlog.cpp主要功能包括日志级别、控制台输出、文件输出和多线程安全写日志用于替代程序中零散的printf。2.2.2config配置模块源码路径config.hconfig.cpp主要功能是解析config.yaml生成摄像头、电机、编码器、IMU、测距、控制器、遥测等配置对象并给缺失字段提供默认值。2.2.3filter滤波模块源码路径filter.hfilter.cpp当前主要提供一阶低通滤波用于抑制IMU yaw rate和编码器RPS的单点跳变。2.2.4 巡线工具函数源码路径tracking_utils.htracking_utils.cppcurvature_calculator.hcurvature_calculator.cpp这些工具主要提供巡线算法中复用的几何计算能力例如点集处理、曲率估计、方向判断等。2.3 驱动模块driversdrivers是硬件驱动适配层。上层模块不直接操作/dev、sysfs、pwm、gpio而是通过这里封装好的C类访问硬件。2.3.1VL53L0X激光测距源码路径vl53l0x.hvl53l0x.cpp主要功能是通过IIO/sysfs读取距离值支持单次读取和后台连续读取。VL53L0X不直接控制电机只负责提供距离信息是否减速或停车由应用层和控制层根据配置判断。2.3.2ST7735显示模块源码路径st7735.hst7735.cpp主要功能是基于Linux framebuffer输出图像支持RGB565格式转换用于显示摄像头巡线调试画面。显示任务属于低优先级任务不能阻塞电机控制线程。2.3.3MPU6050陀螺仪模块源码路径mpu6050.hmpu6050.cpp主要功能是通过Linux IIO读取三轴加速度和三轴角速度计算yaw rate、pitch、roll并给角速度内环提供实际yaw rate。当前IMU初始化阶段不强制自动标定标定动作通过KEY1长按触发。2.3.4 摄像头模块camera源码路径camera.hcamera.cpp主要功能是基于V4L2打开USB摄像头支持分辨率、帧率、像素格式配置支持异步采集、图像翻转和灰度输出为tracking模块提供最新图像帧。2.3.5 电机模块源码路径motor.hmotor.cppmotor_controller.hmotor_controller.cppmotor负责单个电机motor_controller负责左右两个电机。主要功能包括配置PWM周期和占空比、控制方向GPIO、输出左右轮差速占空比并在退出或异常时停止电机。当前巡线控制只输出前进或停转占空比不主动倒车也不依赖左右轮反向来原地反打。2.3.6 编码器模块源码路径encoder.hencoder.cppencoder_controller.hencoder_controller.cpp主要功能是打开左右编码器设备通过ioctl读取编码器速度。当前速度单位为RPSencoder_controller会汇总左右轮速度并提供平均轮速。编码器数据主要用于速度环闭环控制也会通过遥测上传到上位机。2.3.7 按键模块key源码路径key.hkey.cpp主要功能是读取Linux input事件默认设备名为LS2K300 99Pi Keys识别KEY0/KEY1封装短按和长按事件并在双键同时按下时屏蔽单键误触。驱动层只负责事件识别不直接决定业务行为。2.4 巡线模块trackingtracking是Python仿真巡线逻辑的C移植版本负责从摄像头图像中提取赛道信息。2.4.1 源码路径主要源码路径tracking_pipeline.htracking_pipeline.cpptracking_display.htracking_display.cpp2.4.2 基础算法层algorithm包括boundary_scanner边界扫描line_follower根据边界生成中线和误差line_fitter补线corner_detector拐点检测。2.4.3 道路处理层handler包括crossroad_handler十字道路处理left_ring_handler左圆环处理right_ring_handler右圆环处理。复杂道路通常不是1帧图像就能判断完成因此这里会维护阶段状态例如进入圆环、圆环中、出环等。2.4.4 策略层strategy包括normal_road_strategy普通道路cross_road_strategy十字道路left_ring_rad_strategy左圆环right_ring_rad_strategy右圆环barrier_road_strategy障碍道路bridge_road_strategy坡道/桥。2.4.5 巡线主流程一次巡线处理的大致流程如下摄像头图像 - 灰度化/预处理 - 边界扫描 - 拐点检测 - 道路状态判断 - 按道路策略补线/生成目标线 - 计算 tracking_error - 绘制调试图输出结果主要包括tracking_error、road_state、左右边界点、中线点、拐点和调试图像。2.5 核心控制模块corecore不访问具体硬件只处理控制逻辑和状态数据。2.5.1 数据融合data_fusion源码路径data_fusion.hdata_fusion.cpp主要功能是接收IMU yaw rate、编码器左右轮RPS、VL53L0X测距对yaw rate和RPS做低通滤波并生成统一的VehicleState供控制器使用。2.5.2 串级控制器controller源码路径controller.hcontroller.cpp控制器采用“视觉外环 角速度内环 速度环”的结构。外环根据巡线误差计算目标角速度tracking_error - target_yaw_rate角速度内环根据目标角速度和IMU实际角速度计算差速修正target_yaw_rate - actual_yaw_rate - turn_percent速度环根据目标RPS和编码器实际RPS计算基础前进占空比target_rps - actual_rps - base_percent最后进行运动合成left_percent base_percent - turn_percent right_percent base_percent turn_percent正turn_percent表示目标yaw rate为正也就是车体需要左转。差速车左转时右轮应更快因此右轮占空比增加、左轮占空比降低。当前控制器中差速修正只受max_turn_percent和最终电机占空比限幅约束已经移除了max_turn_base_ratio这层限制。2.5.3 周期调度器scheduler源码路径scheduler.hscheduler.cpp主要功能是注册周期任务并按固定间隔执行任务用于LCD回显、遥测上传等低优先级任务。电机控制、视觉处理、编码器采样属于实时性更高的任务不依赖这个普通调度器而是由应用层单独启动实时工作线程。2.6 遥测和上位机2.6.1 下位机遥测telemetry源码路径telemetry_publisher.htelemetry_publisher.cpp遥测模块通过UDP向上位机发送两类数据数据内容状态JSON速度、占空比、误差、角速度、测距、道路状态JPEG图像巡线叠加后的调试画面典型配置如下telemetry: enabled: true host: 上位机IP state_port: 9000 image_port: 9001 state_hz: 20 image_hz: 10 jpeg_quality: 60UDP不保证可靠送达但延迟低适合调车时实时观察最新状态。控制闭环不依赖遥测发送结果即使上位机没有启动小车控制也可以继续运行。2.6.2 上位机upper_monitor源码路径monitor.py安装依赖cd upper_monitor pip install -r requirements.txt运行上位机python3 monitor.py --state-port 9000 --image-port 9001上位机采用左右分栏显示左侧显示下位机上传的巡线图像图像下方显示关键遥测信息右侧显示控制曲线。主要曲线包括巡线误差、目标yaw rate和实际yaw rate、目标RPS和实际RPS、左右电机占空比、基础占空比和差速修正。如果只想看图像不显示右侧曲线可以运行python3 monitor.py --no-plot回到顶部三、构建、部署与测试3.1 构建工程本机编译cd /opt/2k0300/loongson_2k300_lib/car_project cmake -S . -B build -DCROSS_COMPILEOFF cmake --build build -j$(nproc)交叉编译cd /opt/2k0300/loongson_2k300_lib/car_project cmake -S . -B build -DCROSS_COMPILEON cmake --build build -j$(nproc)工程默认使用同级目录下的交叉编译依赖../cross_lib/loongarch64-linux-gnu-gcc13.3 ../cross_lib/opencv-4.10.0 ../cross_lib/googletest-1.14.0也可以使用脚本./scripts/build.sh ./scripts/run.shscripts/run.sh支持上传程序、配置、测试图片和测试视频到开发板也可以远程运行主程序或测试程序。常用环境变量包括REMOTE_HOST 开发板 IP REMOTE_DIR 开发板部署目录 CROSS_COMPILE 是否交叉编译 UPLOAD_IMAGES 是否上传测试图片 UPLOAD_VIDEOS 是否上传测试视频3.2 单元测试安装本机测试依赖sudo apt install libgtest-dev如果要在久久派开发板运行单元测试需要交叉编译GoogleTestwget https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz tar -xzf v1.14.0.tar.gz cd googletest-1.14.0 mkdir build cd build CCloongarch64-linux-gnu-gcc \ CXXloongarch64-linux-gnu-g \ cmake .. -D CMAKE_INSTALL_PREFIX../install make -j$(nproc) make install当前测试目录按模块划分test/ ├── core/ # 控制器测试 ├── drivers/ # 摄像头、编码器、电机、IMU、LCD、测距测试 ├── tracking/ # 巡线算法和策略测试 ├── utils/ # 配置、日志、滤波、几何工具测试 └── videos/ # 测试视频部分drivers测试会访问真实硬件运行前需要确认设备节点、GPIO/PWM权限以及传感器连接状态。没有硬件时建议只运行core、tracking、utils这类纯逻辑测试。回到顶部四、维护原则与代码下载这个工程后续还会继续调参和扩展因此代码结构上尽量遵守几个原则drivers只封装硬件访问不写业务逻辑tracking只负责图像和道路识别不直接控制电机core只处理控制算法和状态融合不访问设备文件app负责把硬件、算法、控制器和任务调度串起来utils保持低耦合避免反向依赖业务模块高频控制线程不能被显示、日志、遥测阻塞所有可调参数尽量放到config.yaml避免写死在代码里。回到顶部五、代码仓库loongson_2k300_lib亲爱的读者和支持者们自动博客加入了打赏功能陆陆续续收到了各位老铁的打赏。在此我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持是我们前行的动力与源泉。日期姓名金额2023-09-06*源192023-09-11*朝科882023-09-21*号52023-09-16*真602023-10-26*通9.92023-11-04*慎0.662023-11-24*恩0.012023-12-30I*B12024-01-28*兴202024-02-01QYing202024-02-11*督62024-02-18一*x12024-02-20c*l18.882024-01-01*I52024-04-08*程1502024-04-18*超202024-04-26.*V302024-05-08D*W52024-05-29*辉202024-05-30*雄102024-06-08*:102024-06-23小狮子6662024-06-28*s6.662024-06-29*炼12024-06-30*!12024-07-08*方202024-07-18A*16.662024-07-31*北122024-08-13*基12024-08-23n*s22024-09-02*源502024-09-04*J22024-09-06*强8.82024-09-09*波12024-09-10*口12024-09-10*波12024-09-12*波102024-09-18*明1.682024-09-26B*h102024-09-30岁102024-10-02M*i12024-10-14*朋102024-10-22*海102024-10-23*南102024-10-26*节6.662024-10-27*o52024-10-28W*F6.662024-10-29R*n6.662024-11-02*球62024-11-021*鑫6.662024-11-25*沙52024-11-29C*n2.882024-12-27*鱼52024-12-30*心2.882025-1-2*新62025-1-6