次日下午,实验室。
夏日的阳光斜射进来,角度比昨天更低一些。光线透过窗户上积累的薄尘,在堆满零件和工具的工作台上切割出明亮的光块与深邃的阴影。
空气里有金属、塑料、松香焊锡膏和旧纸张混合的味道——这是属于我们的气味。
远藤和雨宫已经到了。
远藤正对着电脑屏幕,眉头微蹙,手指在键盘上快速移动,像是在进行一场无声的战斗。
雨宫则半蹲在铺着防静电垫的地上,手里拿着万用表,表笔小心翼翼地探向机器人底盘上一个裸露的传感器模块。
她的呼吸很轻,专注得仿佛整个世界都缩小到那两个测试点之间。
“来得正好,”
雨宫头也没抬,声音有些闷,像是在忍住喷嚏。
“左侧红外传感器的响应时间,比右侧平均慢了0.3秒。诡异。昨天甜品店讨论时还没有这个问题。”
我放下书包,金属搭扣碰撞的声音在安静的实验室里显得很响。
“是不是接触不良?”
“测了电阻,正常。”
雨宫站起身,揉了揉发麻的膝盖。
“但动态响应就是不一致。”
我凑过去。
远藤把一份刚打印出来的信号波形图递给我,指尖点在几个波峰间隔异常宽的位置。
“这是今早的测试数据。你看这里,左侧传感器在收到信号后,电压爬升的时间明显更长。但奇怪的是,静态测试时一切正常。”
我接过图表。
纸还是温的,激光打印机的热度还没完全散去。
那些曲线像心电图,记录着机械的“心跳”。
我们花了两个月时间学习如何阅读这些曲线,如何从微小的起伏中听出故障的征兆。
“昨天全项目测试时还没有这个现象?”
我问。
“没有。最后一次完整测试是前天晚上,所有数据都在公差范围内。”
远藤调出历史记录,屏幕上并列着两幅几乎相同但又有微妙差异的波形。
我们三人极自然地围拢到工作台前,像过去几个月里重复过无数次的场景。
分工无需多言。
我负责检查传感器到主控板的电路连接,远藤调出对应的控制代码段逐行分析,雨宫再次确认机械结构有无物理干涉或松动。
有时候我觉得我们像一台精密的机器,每个部件都知道自己该做什么,无需多余的指令。
空气里是仪器低鸣、散热风扇轻转和键盘敲击的细碎声音。
实验室新安装的空调发出稳定的嗡嗡声,但靠近窗户的地方还是能感觉到阳光的热度。
一只苍蝇撞在玻璃上,发出轻微的啪嗒声,然后继续徒劳地尝试。
我用放大镜顺着柔性电路板的纹路仔细查看。
这块板子是我们自己设计、送去打样的,上面的每一条走线都经过无数次计算和修改。
在靠近接口处,我发现了一丝几乎看不见的、浅金色的细丝,它横跨在两个本不该导通的焊盘之间。
“找到了,”
我用精密镊子的尖头轻轻将其捏起,对着光线看。
“有根猫毛黏在导线触点之间,可能造成间歇性接触不良。动态测试时因为震动,毛绒纤维偶尔会搭接形成微弱通路。”
“啊,肯定是下午溜进来那只三花干的!”
雨宫接过镊子,小心地将毛清除,又用无水乙醇擦了擦触点。
“它总喜欢在零件箱旁边打滚。好了,再测。”
重新接上测试仪。
这一次,两侧传感器的响应曲线几乎完全重合,像是镜面反射。
小插曲解决,但耗费了二十分钟。
雨宫看了眼手机。
“比计划慢了。直接开始正式训练?”
“嗯,从抓取测试开始。”
远藤保存了故障排查记录——我们有个专门的文档,记录每一次问题和解决方案,现在已经写了五十多页。
正式训练开始。
机器人需要在模拟赛道上完成从基础移动到精确抓取、搬运、放置的一系列动作。
赛道是用PVC板和胶带临时搭建的。
实验室模拟了比赛场地的布局。
直道,S弯,坡道,还有三个不同高度的放置台。
每个环节都需要反复调试参数,观察,记录,再调整。
我们轮换角色:一个人操作控制台,一个人观察机器人实时状态,一个人记录数据。
每完成一轮,就交换位置,确保每个人对每个环节都有直观感受。
实验室里只剩下机器电机运转的嗡鸣、履带摩擦测试平台的沙沙声,以及我们之间简短高效的交流。
“抓取机构的伺服电机力度参数需要再微调,”
远藤盯着屏幕上反馈的实时数据流,眼睛几乎不眨。
“上次测试,在模拟湿滑表面,物品有三次轻微滑落记录。虽然最终都抓住了,但浪费了平均0.8秒。”
雨宫在控制台输入指令。
“增加百分之五的静态保持扭矩。现在试试看。”
机器人再次启动。
它的动作比三个月前流畅多了,不再有那种生硬的顿挫感,更像是活物——虽然还是机械的、有限的活物。
我看着它平稳地移动到目标物前,机械爪张开,合拢,抬起,转向,放置。
整个过程用时7.2秒,比比赛规定的上限快了2.8秒。
“成功了?”雨宫问。
“再测五次,”远藤说,“取平均值,看稳定性。”
我们重复了五次。数据很稳定:7.2,7.3,7.1,7.2,7.2。
雨宫在记录表上打了一串勾,嘴角扬起一个明显的弧度。
这是今天第一个值得庆祝的小胜利。
但我观察着机器人执行动作的流畅度,忽然想到一个问题。
“比赛场馆的照明是大型场馆的均匀顶光,”
我说,声音在安静的实验室里显得格外清晰。
“和我们实验室的侧窗自然光加日光灯环境光色温、亮度都不一样。视觉识别的颜色阈值和曝光参数,我们之前有专门针对那种环境调试过吗?”
问题抛出后,有几秒钟的沉默。
远藤操作鼠标的手停住了。
他眨了眨眼,突然抬手拍了下自己的额头,力道不小。
“对,这是个盲点,很细。我们所有的视觉测试都是在实验室条件下做的,自动白平衡虽然能调整,但如果场馆灯光有特殊光谱——”
“——我们的颜色识别可能会出错。”
雨宫接话,脸色沉了下来,“特别是红色和橙色的区分,在钠灯下和LED下完全不一样。”
“但是,”
远藤叹了口气,有些懊恼。
“我忘了,展馆为了布置赛场,最近三天已经闭馆了,我们没办法提前进去做环境测试。”
又一阵沉默。
窗外的阳光继续移动,现在已经照不到工作台,只在地板上留下一块逐渐缩小的光斑。实验室的灯不知道什么时候已经自动亮起,发出冷白色的光。
“有没有可能模拟?”
我问,“查一下场馆的灯光规格,我们调整实验室的照明参数尽量接近?”
“可以试试,”
远藤已经开始搜索,“市政展馆的照明系统去年刚升级过,官网上应该有技术参数……找到了,是飞利浦的LED一体化智能照明系统,色温4000K,显色指数Ra>90。”
“我们实验室的日光灯是6500K,显色指数大概70。”
雨宫快速计算着差异。
“色温差2500K,显色指数差20以上。这肯定会影响颜色判断。”
“把百叶窗全关上,关掉所有日光灯,”
我起身,“用我们带来的摄影补光灯试试。雨宫,你那里不是有两盏可调色温的LED灯吗?”
“在柜子里!”
接下来的两个小时,我们变成了灯光师。我们把实验室弄成了近乎黑暗的状态,然后用摄影灯模拟场馆照明。
调整,测试,失败,再调整。机器人多次将红色方块误判为橙色,或将黄色识别成白色。
“不行,单纯调整相机参数解决不了根本问题,”远藤在第七次失败后说,“颜色空间转换有极限。如果照明条件让两种颜色在RGB空间中的距离小于阈值,再怎么调也分不开。”
“那怎么办?”雨宫的声音里开始有焦虑,“只剩三天了,不可能重写整个视觉识别模块。”
我看着机器人再次将一个红色方块放到橙色区域,然后因为“任务失败”而停在原地,像是困惑的孩子。
它的摄像头茫然地对着前方,镜头反射着我们的补光灯,像小小的、呆滞的眼睛。
“也许,”我缓缓地说,“我们不需要它百分之百准确地区分颜色。”
他们两人看向我。
“比赛规则说,机器人需要将不同颜色的方块放到对应颜色的区域。但并没有要求它必须通过颜色识别来做到这一点。”
我走到赛道旁,拿起一个红色方块和一个橙色方块,“你们看,除了颜色,这些方块还有什么不同?”
雨宫凑近看:“形状都一样,都是立方体……等等,重量?”
“材质不同。”远藤立刻明白了。
“红色的是实心ABS塑料,橙色的是发泡EVA包覆配重块。虽然外观尺寸一样,但密度不同,所以重量有细微差别。”
“多少?”
远藤快速在平板上查找资料:“红色方块单重50克,橙色方块单重52克,差2克。”
“2克……”雨宫皱眉,“我们的压力传感器能分辨吗?”
“理论精度是0.5克,”
我说,“但实际应用中,因为机械振动和传感器噪音,可能需要更大的差值才能稳定识别。”
“那就需要测试。”
远藤已经站起来,“如果可行,我们可以在抓取后增加一个称重步骤,根据重量判断颜色。虽然会多花0.3到0.5秒,但可靠性会大幅提升。”
“比误判导致重新抓取要好,”
雨宫点头,“误判一次至少浪费3秒。”
于是我们又投入新一轮测试。
在机器人机械爪的内部加装高精度压力传感器我们早有预留——原本是为了检测抓取力度,现在派上了新用场。
修改控制程序,让机器人在抓取物体后、移动前,先读取压力值,判断物体类型,再决定放置目标。
编写,调试,上传,测试。
第一次:成功区分。
第二次:成功。
第三次:橙色误判为红色。
第四次:成功。
第五次:成功。
“成功率百分之八十,”远藤盯着数据,“不够。”
“可能是抓取时施加的力不均匀,”我分析,“导致压力传感器读数波动。可以在抓取后增加一个稳定化动作,等读数平稳后再判断。”
“会增加0.2秒。”
“但能把成功率提到百分之九十五以上。”
“值得。”
修改,再次测试。
这一次,二十次测试全部正确。
机器人抓取,稳定,判断,转向,放置。
动作没有因为新增的步骤而显得稍有停顿,但准确无误。
窗外的天色,就在我们这一次次调试、争论、修改中,不知不觉染上了茜色,又渐渐沉淀为鸽子身上那种红灰色。
远处商业街的霓虹和路灯次第亮起,像是有人在缓慢地点亮一串珍珠项链。
实验室里,只有我们的屏幕还发着光,将三人的脸映成冷色调。