制造一个可以自动追踪对象的智能扇风机器人
我的风扇指向我曾经所在的位置
桌面风扇会朝你上次放置的方向吹风。当你移动椅子、弯腰看书,或转身与人交谈时,空气却从耳边掠过,而不是直接对着脸。于是你又得伸手重新调整它。
我桌上有一台myCobot 280,突然想到:这正是机器人手臂应该解决的那种愚蠢、微小但真正令人烦恼的问题。不是工厂生产任务,而是让风扇持续地朝我的头部吹风,而没有任何指令。
我给自己定下的规则是:不加额外传感器。没有深度摄像头,没有立体声装置,也没有贴在额头上的标记点。只用笔记本电脑机盖内置的摄像头即可。
它是如何工作的?
这台风扇的价格大约和一瓶水相当
myCobot 280 M5 的底部搭载了 M5Stack 单元,提供了 GPIO 接口。这意味着我可以直接通过机械臂为小型设备供电,而无需额外使用 USB 线缆。于是,我上网找了一个电流消耗较小的风扇,最后只花了几美元就找到了一个。
选择小尺寸也是出于空间清空的考虑。手臂在运动时可以折叠到相当多的角度,如果风扇太大,挂在末端执行器上,最终会摆动并撞击关节。而小型风扇无论朝哪个方向都与手臂本身保持距离。它的气流强度比我预期的要强——确实能明显感受到,但若想真正实现有效散热,而不是仅仅让空气掠过面部,显然需要升级到更大的风扇。这也就意味着我必须更仔细地权衡间隙问题以及手臂250克的负载限制。
风扇末端带有PH2接口,这并不是我能直接插进自己设备上的类型。一位同事为我焊接了一根杜邦跳线连接到引线上,之后它直接接入了5V电源轨。
接着我将线路接反:正极接大地,负极接正极。卖家的列表中特别警告过,反转极性会损坏风扇,而我无论如何还是成功做到了这一点——它在那里静止了几秒,之后我才意识到自己做了什么,赶紧把它拆了下来。
不过它挺过了。正确接线后,风扇运转得非常顺畅,从那以后一直正常工作。这更多是运气,而非我做对了什么。许多小型无刷风扇没有反向极性保护功能,在这种情况下会无声地烧毁。在连接任何设备前,请先检查外壳上的标识——而这正是我本该做的。
用纳米胶带固定,因为我不会3D打印
myCobot 280 的末端执行器有乐高兼容的安装孔,这确实是个贴心的设计——前提是你要安装的部件也有对应的乐高孔位。但我的风扇只是一块五美元的风扇,没有这样的接口。正确的做法是设计并打印一个小型适配支架。可惜我不懂3D打印。
所以我只好用了纳米胶带。虽然这不是工程解决方案,但在这个情况下效果还不错。它质地厚实且略带弹性,能将重量均匀分散到风扇背面的整个区域,而不是集中在少数几个点上,还能吸收部分电机振动,避免将其传递到支架上。此外,它还可以拆卸,这一点在你还在犹豫角度时尤其重要。对于这么轻的物品,它的固定效果远超我的预期——我还没弄断过。
如果你能打印,就打印一个支架;如果不能,这个方法也行。
从单个摄像头获取深度信息
这个项目最困难的部分并不是机械臂,而是确定你的脸部在三维空间中的确切位置。单个摄像头只能告诉你脸部的方向,但无法提供距离——而没有距离,就无法对任何物体进行瞄准。
关键在于测量你脸部上一个已知实际尺寸的参考点。我使用的是双眼之间的距离。MediaPipe 的面部地标模型输出了 478 个点,包括两个虹膜中心,因此我测量虹膜之间的像素距离。这个距离与你离摄像头的距离成反比,结合相机的焦距,就能直接换算为米。
代码假设的数值是 63 毫米,这大致接近成年人的平均值。请注意,这是一个假设,并非固定不变的值——成年人的瞳孔间距通常在 52 毫米到 78 毫米之间,因此处于较短端的人会读取到明显更近的距离。这一点在这里影响不大,因为我是唯一的使用者,且该数值是配置参数:只需坐在一个已测得的距离处,调整直到屏幕上的深度显示与实际一致即可。但如果要为任意人群开发此功能,则需要妥善处理这一问题。
我的第一个版本使用了面部边界框的宽度来实现这一点,这是一种更直观的方法,但效果却差得多。随着检测器置信度在不同帧之间变化,框边缘会不断晃动,因此即使你完全静止坐姿,估计的距离也会时而增大、时而减小。虹膜特征则清晰且稳定。静止坐姿下的深度读数保持在0.68米,标准差为34毫米。
接下来你需要知道相机相对于手臂的位置,这只需从手臂基部到摄像头镜头测量三个距离:向前的距离、向侧的距离以及向上距离。这些信息被输入配置文件中,代码会将你的面部位置从相机坐标系转换为手臂坐标系。
如果不需要,就不要求解六轴逆运动学问题。
风扇具有旋转对称性,它并不关心自己朝哪个方向上——只关心其指向的方向。这使得原本复杂的六轴逆运动学问题变得简单得多,也更加数值稳定。
我将其拆分为:
● 关节1使底座旋转,从而使手臂的工作平面转向面向你。
● 关节2和关节3将手腕固定在该平面内一个舒适的位置——远离桌面,避开奇点。这些位置始终不变。
● 关节4调节风扇的高度,使其轴线指向你的面部。
● 关节5和关节6则完全静止不动。
唯一需要注意的是,风扇位于手腕关节前方,因此旋转手腕时也会带动风扇移动,从而改变了最初所需的朝向角度。求解器只需迭代三次即可收敛。经与工作空间内的正向运动学验证,最终的瞄准误差为0.000度。
它追踪的是门框而不是我
我使用的第一个检测器是OpenCV的Haar级联算法,这是传统的人脸检测快速方案,但在此处并不适用。它大约每四帧中就有一帧能识别出我的脸部。更糟糕的是,偶尔它会误判我身后的门框比我的真实脸部更“合适”——由于我的代码选择了最大的检测结果,门框便胜出,手臂随即从我身边摆开,转向墙壁。
Haar级联算法依赖于明暗矩形的模式,因此明亮的门框与较暗的墙面相映衬时,会触发许多与人脸相似的特征。这并不是一个漏洞,而是该方法所能识别的极限所致。
切换到MediaPipe地标模型后,问题完全解决了。在八秒的测试中,检测率从大约25%提升到了107帧中的107帧,误报也彻底消失了——该模型现在是在寻找真实的面部几何结构,而不仅仅是边缘图案。虽然速度有所下降,循环频率从26赫兹降至约13赫兹,但13赫兹远足以跟踪一个人在椅子上移动的情况。
它在哪里
它确实有效,会在我桌面上来回移动,空气也会落在我的脸上。
风扇重量为30克,支架承重250克。我在这里并未用尽预算——还有超过200克的余量,这说明风扇本身已经足够大了。因此,接下来最自然的一步就是换一个更大的风扇。阻碍我的不是重量,而是空间限制:支架在追踪时能折叠到较宽的角度范围,而如果风扇尺寸更大,极端位置时风扇就会开始进入支架自身的关节部位。这是一个需要解决的几何问题,而非硬性限制,因此可能更应该考虑调整风扇的安装位置,而不是缩小风扇本身。
我遇到的一个真正限制是第4个关节,当向上抬升约35度时,它的行程就已耗尽。我坐着时大约只有15度,所以它无法上升。但如果我站得离支架很近,它就能达到极限位置,在屏幕上显示并固定不动,不再强行挤压。将手腕位置调高一些,可能是更好的选择。
下一步明显应该是通过M5Stack的GPIO开关风扇的开关,而不是让它持续运行——当有脸出现时打开,当我离开时关闭。这需要在引脚和风扇之间加一个MOSFET,因为ESP32的GPIO只能提供约40 mA的电流,而即使是这么小的风扇,其耗电也远超这个范围。直接将电机连接到GPIO引脚上,是毁坏电路板的一个好方法。
除了风扇之外,任何指向代码都不关心末端接的是什么。同样的管道可以将灯光、摄像头或麦克风对准正在说话的人。
为什么选择myCobot 280?
myCobot 280 M5 X版机械臂结合了紧凑的6自由度设计与基于Python的控制,使其成为计算机视觉和物理AI项目灵活的平台。
本文编译自hackster.io





