九月一,周一,七点三十分。
天刚亮,京市的秋意还藏在晨雾里。王波站在启明未来B座楼下,没看玻璃幕墙反射的朝阳,只低头检查双肩包拉链——逻辑分析仪、万用表、三套杜邦线、备用保险丝、那本翻烂的《ARM Cortex-M权威指南》,一样不少。衬衫是新买的,但袖口已微微卷起,露出小臂上一道浅疤——那是大三焊电源模块时烙铁烫的。他没熨平,因为知道,今天肯定要蹲在测试台前。
前台刷身份证,领临时工牌。
“感知系统部,底层驱动组,周工等你。”
他点头,乘电梯上三楼。
走廊尽头第三间,门牌写着“底层驱动组”。推门进去,六张工位,五台显示器亮着。空调开得很足,混着松香、咖啡、电路板清洗剂和一丝若有若无的焊锡味——那是工程师的体味。
老周从角落抬头,格子衫袖口沾着松香灰,手里正用镊子夹一颗0402电容。
“来了?”
“嗯。”
“工位在窗边,电脑已配好。账号密码在便签上。”
王波走过去,放下包。桌上贴着一张黄纸:“user: wangbo / pwd: Qm2024!drv”。旁边放着一块开发板、一JTAG线、一本打印的《LSD-V2硬件手册》。他没急着开机,先用万用表测了下开发板VCC对地阻抗——8.2kΩ,正常。又检查JTAG接口针脚是否歪斜。确认无误,才电。
旁边工位的年轻人探头,黑框眼镜,头发微卷,T恤印着“ROS is not real-time”:
“你就是王波?我李峰,京航大学控制工程硕士。”他语气带点试探,“听说你是985本科?怎么进来的?”
王波没看他,只盯着屏幕登录GitLab:
“面试过了。”
李峰不以为忤,反而兴奋:“我看了你GitHub!AidWalker那个双阈值台阶检测,用了动态基线校准,对吧?其实理论上可以用卡尔曼滤波统一处理,但你选了状态机,是为了降低延迟?”
王波终于转头,眼神平静:
“卡尔曼需要协方差矩阵初始化,老人走路节奏不规律,初始噪声难估计。状态机虽然糙,但确定性高。”
李峰眼睛一亮:“对!我就说你不是乱做的!”
对面工位,一个穿 polo 衫的男人放下枸杞茶杯,杯底贴着“刘敏-通信组”标签:
“新来的?我是刘敏。”他指指隔壁埋头看示波器的男人,“张立伟,IMU驱动五年。”
张工没抬头,只从鼻子里“嗯”了一声,手指在示波器旋钮上微调,屏幕上的SPI时钟波形立刻变得净利落。
靠门的位置,寸头男人正用热风枪吹一块PCB,烟雾缭绕:
“赵海军。”他头也不抬,“以后CAN总线有问题,先自己抓包,别一上来就问。问之前,至少得知道0x7E8是诊断响应帧。”
王波点头:“明白。”
老周走过来,递给他一块开发板:
“这是LSD-V2主控,STM32H743,480MHz。你的第一个任务——把 AidWalker 里的IMU温漂补偿方案,移植到这块板上,跑通数据采集,输出补偿后姿态角。”
王波接过板子,沉甸甸的。
“用什么IMU?”
“MPU6050,和你原来一样。”
“温度传感器?”
“板载DS18B20,靠近IMU位置,走单总线。”
“采样率?”
“IMU 200Hz,温度1Hz。”
“任务调度?”
“FreeRTOS,IMU采样任务优先级最高,温度补偿次之。”
老周眼中闪过一丝赞许——他问的都是关键约束,而不是“能不能做”。
“下午两点,标定室。”老周转身,“赵海军带你。”
上午十点,部门例会。
会议室小,八个人挤着坐。老周主持,语速快如示波器扫描:
“LSD平台Q3目标:亦城园区配送实测,均50单。当前瓶颈:雨天+高温下IMU零偏漂移,导致定位跳变超0.5米。”
他看向王波:
“你负责温漂补偿模块,两周内出原型,必须支持在线更新查表。”
又转向李峰:
“你配合做数据标注工具,Python写,只标时间戳、IMU原始值、温度、补偿后姿态。别整花活,别引入第三方依赖。”
李峰推眼镜:“能不能用ROS2的bag recorder?它有标准化的时间同步……”
老周皱眉:“LSD平台没ROS,只有FreeRTOS。工具只要能读串口、写CSV就行。”
李峰缩了缩脖子,小声嘀咕:“但ROS2的time API更精确……”
赵海军冷笑一声:“你先让串口不丢帧再说。”
散会后,李峰凑到王波工位:
“你说,为什么不用Kalman?理论上最优啊。”
王波打开AidWalker的志文件,调出一段雨天行走数据:
“你看这里——老人突然停住,IMU加速度突降,但陀螺仪还有残余角速度。Kalman会把这当成‘过程噪声增大’,放大协方差,导致后续几帧过度信任GPS。但我们没有GPS。”
他指着状态机跳转记录:“我直接切到‘静止模式’,锁死姿态输出,等加速度稳定再恢复。虽然粗暴,但安全。”
李峰盯着屏幕,半晌才说:“……你考虑的是失效边界,不是理想模型。”
王波没接话,只说:“工程里,99%的问题出在边界。”
中午食堂,六人一桌。
刘敏夹菜时说:
“王波,你那个AidWalker,ISR里是不是直接驱动电机?”
“嗯,高优先级任务。”
“小心堆栈溢出。”刘敏喝口枸杞茶,“我们这儿ISR只设标志位,处理放任务里。上次李峰想在ISR里malloc,被老周骂了半小时。”
李峰脸一红:“我以为FreeRTOS支持……”
张工突然开口,声音低沉如接地线:
“ISR里别调printf。”
全桌静了一秒,然后赵海军笑出声:“张工金句又来了。”
下午两点,标定室。
恒温箱、振动台、数据采集仪排成一列。赵海军作设备,动作利落如拧螺丝:
“先从25度开始,每5度升一次,每次稳30分钟,记录零偏。全程不通电,避免自热扰。”
王波接线,接DS18B20,接MPU6050,接地线。动作熟练,焊点圆润。
赵海军看着他用热缩管包覆接头,忽然说:
“你以前真送外卖?”
“嗯。”
“难怪手稳。我见过太多硕士,连烙铁都拿反。”
标定持续三天。
王波每天记录201个温度点下的零偏数据,整理成CSV。晚上回出租屋,用Python拟合曲线,发现线性模型在40℃以上误差陡增,而分段查表+线性值最稳。
他没直接用李峰写的标注工具——太慢,串口缓冲区溢出频繁。
他自己用C写了个轻量版,基于环形缓冲区,加了流控,采样率提升三倍。
第二天早上,他把工具发给李峰:
“试试这个,支持115200波特率不丢帧。”
李峰运行后惊了:“你昨晚写的?这比我的快五倍!”
“你用了PySerial默认缓冲,我改了底层read timeout。”王波平淡地说,“工程工具,先保证可靠,再谈优雅。”
李峰沉默良久,最后说:“……我请你喝茶。”
周五,王波提交第一版补偿算法。
他在FreeRTOS里建了两个任务:
imu_sample_task:200Hz采样,进ISR存原始数据;
temp_comp_task:1Hz读温,查表更新偏置,滑动窗口滤波。
测试结果:40℃环境下,零偏漂移从0.8°/s降到0.15°/s。
老周 review 很快,只提一条:
“ISR里别用浮点运算。改成定点。”
王波立刻改了,用Q15格式重写查表值,精度损失<0.5%。
李峰跑来问:
“你这补偿模型,能不能输出不确定性?我想喂给后面的卡尔曼滤波。”
“可以加个方差输出字段。”
“太好了!”李峰眼睛发亮,“这样融合层就知道什么时候信IMU,什么时候不信。”
王波却摇头:“别直接喂方差。加个滞后判断——连续5帧偏差超阈值,才降权。否则单点噪声会误触发。”
李峰愣住:“……你怎么想到的?”
“林秀云摔过一次。”王波声音很轻,“就因为单点误判,机器锁死了。”
李峰没再说话,回去默默改了融合逻辑。
周一清晨,五人乘车去亦城测试场。
测试场在郊区,围栏高耸,地面划着各种标线。LSD-07 是一台白色小车,顶着激光雷达和摄像头,底部装着履带。
赵海军接电源,李峰调试串口,张工检查IMU固定螺丝。
王波蹲在车底,看DS18B20的走线。
“走线太长,可能受电机扰。”
他掏出屏蔽线,重新绕了一遍,就近接地。
十点,开始测试。
第一轮:室内恒温走廊。定位稳定。
第二轮:室外暴晒石板路。阳光直射,车体温度迅速升至42℃。
监控屏上,原始IMU数据开始漂移,但补偿后的姿态角平稳。
老周盯着屏幕,没说话。
第三轮:模拟雨天,洒水车刚过。
LSD-07驶过水渍,履带打滑。定位系统短暂跳变,但三秒内恢复。
李峰喊:“融合层没崩!温漂补偿起作用了!”
中午休息,刘敏送来盒饭,还有一包新保险丝。
“张工说你们早上差点烧板子?”
赵海军笑:“王波眼疾手快,拔电源比谁都快——电机堵转电流超限,他直接断电,没等看门狗复位。”
下午最后一项:连续运行两小时,监测温升累积效应。
王波坐在遮阳棚下,看实时志。温度从28℃升到51℃,偏置补偿始终有效。
老周走过来,递给他一瓶冰水:
“不错。”
就两个字。
但王波知道,这比“得漂亮”更重。
回程车上,李峰兴奋地说:
“我觉得可以把这个模块做成独立库,叫‘RobustIMU’!”
赵海军泼冷水:“先让它在亦城跑满一千公里再说。”
张工闭着眼假寐,忽然嘟囔一句:
“别忘加看门狗。”
全车人笑了。
周二上午,组内技术讨论。
李峰提议:“我们应该把温漂模型参数化,支持不同IMU型号。”
赵海军反对:“参数化增加复杂度。我们现在只用MPU6050,何必抽象?”
两人争执不下。
王波一直没说话,直到老周问:“王波,你怎么看?”
他打开笔记本,调出三张图:
“第一,AidWalker用MPU6050,LSD-V2也是;第二,下一代平台计划用ICM-42688,温漂特性不同;第三,查表数据占内存不到2KB。”
他顿了顿:
“我建议:保留当前实现,但把查表数组定义为外部链接符号。换IMU时,只需替换数据文件,不改逻辑。”
老周点头:“就这么办。”
李峰佩服:“你平衡了扩展性和简洁性。”
赵海军也服气:“行,听你的。”
周三,张工主动找王波:
“你的补偿查表,用了多少点?”
“11个,从20到70度。”
“太少。”张工递给他一个U盘,“这是我标定的201点数据。用这个。”
王波愣住:“谢谢张工。”
张工摆摆手,继续盯他的示波器。
当晚,王波整合新数据,补偿精度进一步提升。
他提交PR,备注写:
“Thanks to Zhang Liwei for calibration data.”
周四,刘敏教他配置JTAG调试环境:
“别用ST-Link原装线,太长,信号衰减。我们自己焊的短线,看——”
她拿出一不到10cm的扁平线,“阻抗匹配,烧录快一倍。”
王波记下,周末自己焊了三条备用。
周五,陈思阳路过底层驱动组门口,脚步稍顿。
她没进来,只朝里面看了一眼。
老周正好抬头,两人目光碰了一下。
她微微颔首,走了。
没人说话,但王波知道,她在看进展。
当晚,王波回了一趟出租屋。
王涛不在,桌上留了张纸条:“去实验室调PID,晚归。”
冰箱上贴着电费单,房租通知。
他煮了碗面,吃完,打开 AidWalker_V3,给林秀云打了个电话:
“阿姨,机器还好用吗?”
“好用!昨天我还去了超市!”
“下雨天呢?”
“不怕!你上次加的那个‘防滑模式’,真灵!”
挂了电话,他坐在床边,望着窗外。
京市的夜空看不见星星,但远处科技园的灯光连成一片,像一块巨大的电路板,正在上电。
他知道,自己不再是那个只能修助行器的人了。
但他也没变成“大厂工程师”。
他只是……找到了一群愿意一起看波形、一起焊排针、一起为0.1度偏移较真的人。
而这一切,才刚刚开始。
周六,公司加班。
李峰在调融合层,遇到性能瓶颈。
“CPU占用太高,FreeRTOS任务切换开销大。”
王波过去看代码,发现他在每个任务里都用vTaskDelay(1)做1ms延时。
“别用delay。”王波说,“用定时器中断触发任务。”
他现场改了一版,用TIM2中断唤醒任务,CPU占用从78%降到42%。
李峰震惊:“你怎么知道这个技巧?”
“FreeRTOS手册第127页。”王波平淡地说,“还有,你没开编译器优化-O2。”
李峰:“……我这就开。”
周,赵海军约王波去电子市场。
“买点钽电容,LSD-07电源纹波还是大。”
两人在柜台前挑元件,赵海军忽然说:
“你知道吗?老周当年也是送外卖的。”
王波一愣。
“真的?”
“嗯。名校退学,送了三年外卖,自学嵌入式,后来被陈总监挖进来。”赵海军笑,“所以他说你简历‘不像学生写的’。”
王波没说话,只是把选好的电容放进塑料盒。
回程地铁上,他想起老周第一次见他时说的话:“暴雨那天,焊点不错。”
原来,他早看懂了。
九月十五,LSD平台通过Q3初验。
老周在组会上宣布:
“温漂补偿模块正式纳入主。王波,你负责维护,并支持后续平台迁移。”
他又看向李峰:“融合层稳定性提升,功劳一半在底层。”
李峰站起来,认真对王波鞠了一躬:“谢谢你,让我知道什么叫工程。”
王波摇头:“是你愿意听。”
散会后,刘敏递给王波一个新工牌——蓝色,正式员工。
“欢迎上电。”她说。
王波接过,别在前。
金属卡扣“咔”一声扣紧。
他知道,这一声,比任何掌声都响