1. 硬件选型与开发环境搭建第一次接触智能车竞赛的同学可能会被琳琅满目的硬件设备搞得眼花缭乱。我当年参加第十八届比赛时光是选核心板就纠结了两周。现在回头看其实只要抓住几个关键点硬件选型并不复杂。1.1 核心板选购指南市面上主流的TC264核心板供应商就两家逐飞和龙邱。我的建议是全套设备尽量选择同一家因为不同厂家的接口定义和配件兼容性会有差异。比如龙邱的下载器用在逐飞核心板上就可能出现接触不良的情况。这里有个省钱小技巧可以去二手平台淘成色较好的核心板套装包含核心板、母板和下载器价格能比全新便宜40%左右。但要注意检查芯片引脚是否有氧化最好让卖家提供基础功能测试视频。1.2 开发环境配置实战TC264必须使用英飞凌官方的AURIX Development StudioADS开发环境。最新版本已经支持中文界面对新手友好很多。安装时注意以下几点JDK版本要选1.8ADS对高版本兼容性不好安装路径不要有中文和空格首次使用需要导入设备支持包配置工程模板时建议直接使用逐飞提供的例程包。他们的代码结构清晰关键函数都有详细注释。我整理了一份配置清单# 开发环境组件清单 - ADS 1.9.82023稳定版 - Tasking编译器插件 - J-Link驱动v6.98b - TC264设备支持包v2.1.61.3 摄像头选型与安装总钻风摄像头MT9V034是性价比之选价格在200-300元之间。安装时要注意支架高度建议15-20cm太低视野受限太高图像畸变大俯仰角控制在30°-45°之间使用3M胶扎带双重固定比赛时震动很大有个容易忽略的细节摄像头电源要加磁珠滤波。我们车队曾经因为电源干扰导致图像出现横纹调试了整整三天才发现是这个问题。2. 图像采集与基础处理2.1 摄像头驱动开发逐飞的例程里有个display_demo工程可以直接输出灰度图像到LCD屏。我建议先从这个例程入手理解三个关键参数#define MT9V03X_W 188 // 图像宽度 #define MT9V03X_H 120 // 图像高度 uint8 mt9v03x_image[MT9V03X_H][MT9V03X_W]; // 图像缓存数组实际比赛时图像分辨率不需要太大。我们的实测数据188x120分辨率下帧率可达60fps320x240时帧率降到25fps图像每增加1行处理时间增加约0.8μs2.2 大津法二值化优化大津法Otsu是自动确定二值化阈值的经典算法。原始算法有计算量大的问题我优化后的版本速度提升3倍uint8 otsuFast(uint8 *img, uint16 w, uint16 h) { uint32 hist[256] {0}; // 简化版直方图统计 for(uint32 i0; iw*h; i) hist[img[i]]; float sum 0, sumB 0; uint32 wB 0, wF 0; float varMax 0; uint8 threshold 0; for(uint8 t0; t256; t) sum t * hist[t]; for(uint8 t0; t256; t) { wB hist[t]; if(wB 0) continue; wF w*h - wB; if(wF 0) break; sumB (float)(t * hist[t]); float mB sumB / wB; float mF (sum - sumB) / wF; float var (float)wB * (float)wF * (mB - mF) * (mB - mF); if(var varMax) { varMax var; threshold t; } } return threshold; }实测效果对比传统算法每帧处理时间2.3ms优化算法每帧0.7ms阈值误差±3个灰度级对赛道识别无影响3. 赛道识别与循迹控制3.1 边线提取算法最基础的扫线法虽然简单但在复杂赛道容易丢线。我们改进的双向预测扫线法稳定性提升明显void findEdgeLines() { for(int ySTART_LINE; yEND_LINE; y--) { // 从左向右扫 for(int xmid_line[y-1]-10; x3; x--) { if(isEdgePoint(x,y)) { left_line[y] x; break; } } // 从右向左扫 for(int xmid_line[y-1]10; xw-3; x) { if(isEdgePoint(x,y)) { right_line[y] x; break; } } // 中线计算 mid_line[y] (left_line[y] right_line[y]) / 2; } }3.2 元素识别技巧环岛识别有三个关键特征单侧连续丢线超过15行有效边线曲率突然增大赛道宽度变化率超过阈值我们的状态机实现方案enum RoundaboutState { DETECTING, ENTERING, IN_LOOP, EXITING }; void handleRoundabout() { static enum RoundaboutState state DETECTING; switch(state) { case DETECTING: if(checkEnterCondition()) { startPathPlanning(); state ENTERING; } break; case ENTERING: if(checkInsideLoop()) { adjustPath(); state IN_LOOP; } break; case IN_LOOP: if(checkExitCondition()) { recoverNormalPath(); state EXITING; } break; case EXITING: if(isStraight()) { state DETECTING; } break; } }4. 运动控制与参数整定4.1 双环PID控制器设计速度环和方向环建议先用独立PID调试稳定后再改为串级。我们的参数经验值控制环PID输出限幅速度环0.80.050±8000方向环1.20.010.3±30调试时注意先调P直到出现轻微震荡加D抑制震荡最后加I消除静差4.2 差速转向实现对于三轮车模差速控制比舵机更灵敏。核心代码void setMotorSpeed(int left, int right) { left constrain(left, -MAX_PWM, MAX_PWM); right constrain(right, -MAX_PWM, MAX_PWM); if(left 0) { pwm_set_duty(LEFT_GO, left); pwm_set_duty(LEFT_BACK, 0); } else { pwm_set_duty(LEFT_GO, 0); pwm_set_duty(LEFT_BACK, -left); } if(right 0) { pwm_set_duty(RIGHT_GO, right); pwm_set_duty(RIGHT_BACK, 0); } else { pwm_set_duty(RIGHT_GO, 0); pwm_set_duty(RIGHT_BACK, -right); } }5. 调试技巧与性能优化5.1 图像调试工具推荐使用逐飞的无线图传模块上位机可以实时查看处理效果。如果预算有限可以用串口发送图像数据在MATLAB中显示% MATLAB图像显示代码 fid fopen(image.bin,rb); img fread(fid,[188,120],uint8); fclose(fid); imshow(img);5.2 内存优化技巧TC264的CPU0和CPU1内存是分开的CPU0内存存放核心控制代码CPU1内存放图像处理代码使用__section__关键字指定存储位置// 将图像缓存放在CPU1内存 __section__(.cpu1_ram) uint8 image[120][188];5.3 比赛现场应急方案准备备用核心板烧写好基础程序带齐各种连接线杜邦线、USB线等准备不同焦距的镜头应对光线变化备用电池至少3组记得比赛前用热熔胶固定所有接插件我们吃过接插件松动的亏。最后建议每天结束前备份代码用Git或者简单打包压缩都可以。