一些C++类与对象的基础
这一部分需要读者自学,不用太过于深入,只需要知道在C++中类如何建立、如何在类中定义函数并且如何在类外调用即可。
下载开源
访问链接https://github.com/hccc1203/RunACCM2025 按照下图所示操作。


在vscode中打开RunACCM2025-main文件夹。

代码结构
主要文件作用说明
main.cpp:线程创建与整体调度入口standard.cpp:核心巡线与决策逻辑general.h:常用工具函数封装cross.cpp / cross.h:十字元素处理模块ring:圆环相关算法实现
本程序主要使用的是生产者-消费者多线程模型,下面代码展示了整个程序的线程结构,是理解本项目运行机制的关键。
1 | std::vector<PredictResult> predict_result; |
由上述代码可以知道,在不开启显示的情况下我们一共启动了三个线程,分别是task_producer,AI_producer,task_consumer。这三个线程分别有什么用呢,我们可以通过vscode跳转至其执行函数
task_producer
1 | bool producer(Factory<TaskData> & task_data, Factory<TaskData> & AI_task_data, Config & config) { |
不难看出,这个线程主要的任务就是采集图像并生成类型为TaskData的结构体,并将其放入AI_task_data和task_data的队列中去,以便于AI_producer和task_consumer两个线程调用。
AI_producer
1 | bool AIConsumer(Factory<TaskData> & AI_task_data, std::vector<PredictResult> & predict_result, Config & config) { |
这个线程主要功能就是从AI_task_data拿出一个TaskData类型的结构并用于AI推理,并将推理结果放入predict_result这个全局变量中(本质上是PredictResult结构的有向数组)
task_consumer
1 | bool consumer(Factory<TaskData> & task_data, Factory<DebugData> & debug_data, std::vector<PredictResult> & predict_result, Config & config, shared_ptr<Uart> & uart) { |
这个线程就是我们智能车的主要线程了,从代码中可以看到这个线程主要从task_data队列中获得一个包含图片、时间等数据的结构体,并将图片和AI推理结果传入Standard大类中的run函数,这个函数也返回一个结构体,其中包含了车辆目标速度、车辆目标打角等信息,再使用串口将这些信息发送至下位机TC264中进行处理。
那么接下来我们着重介绍一下Standard这个大类。
Standard类run函数解析
Standard.run函数分为以下几个部分:基础巡线、元素检测、元素处理、中线选择、偏差计算、速度判定、运行控制。接下来我将逐个讲解。
基础巡线部分

元素检测及处理
此处以十字识别及处理为示例
1 | /* ***************************************************************** */ |
我们在程序开始时定义了一个名为scene的枚举体,并将其初始化为NormalScene。在Cross.h文件对Cross类的定义中,我们又根据车辆经过十字路口时的过程和状态将其分类,如图六所示


有细心的读者应该观察到,我们此处还有一个判断_elem_order[order_index] == 6的操作,这是我们团队的小巧思。我们在程序开始时定义了一个_elem_order数组并将order_index初始化为0,这个数组中存放的是整个赛道所有元素的顺序,我们检测完一个元素,order_index就加一,可以做到按顺序检测元素,从而降低算力消耗和误判概率。
此外,基于这套系统,我们还可以做出针对赛道的分段速度或分段预瞄点。在杭电国赛第一天,我们就是降低了第一个元素前赛道的速度才得以完赛。
1 | "elem_order":[5,6,6,6,6,5,2,0,6,6,5,5], |
中线选择
这一部分并没有什么特别的,只是根据前面所选择的trackState来将不同的中线存放到t_CenterEdge这个有向数组中,防止混乱。
偏差计算
1 | // 找最近点(起始点中线归一化) |
这段代码的主要思想即为纯跟踪,B站上有许多讲解纯跟踪原理的视频,大家可以自行观看。省略的代码是在每一种场景下远预瞄点和近预瞄点不同的权重。
剩余部分
剩余部分主要是不同场景下的速度控制以及PD计算出舵机打角值,对于走马观碑和燕过留痕组用处不大,各位读者可以选择性观看。
结语
希望这篇文章能够帮助你建立一种阅读智能车开源代码的思路:先看结构,再看数据流,最后深入算法细节。后续我也会围绕基础巡线、元素算法、参数设计和调试方法,继续对这套系统进行更细致的讲解,帮助更多同学真正做到“看得懂、改得动、用得稳”。