XMove是沙漠君和几个死党从2010年开始开发的一套人体动作捕捉系统,软硬件全部自行开发,投入了大量的精力,历经三年,发展四个版本。文章分上下篇,本文为下篇,前三代的故事在《光荣与梦想| XMove动作感应系统(一)》,建议阅读。
2012年的最后一天,我安静地走出科研楼的大门,那一天,我停止了对XMove所有的开发和维护。这个我曾为其痴迷,痛苦和成长的项目,正式成为了过去式。
然而2011年暑假,本科毕业刚喝完散伙酒的我才不这么想,制定了一大堆目标,兴冲冲的上路了:
第四代的小目标:赚它一套学区房
如果我们想捕捉人体完整的动作,至少需要23个节点。但前三代因为条件所限,只有手脚四个节点。第四代传感器覆盖了从头到脚的每个关键位置,最终效果是这样的:
穿上这套服装,然后在广场打一套太极拳,传感器就会通过无线传递给手机,手机利用无线网络传回电脑,系统会记录和分析每一个动作细节,然后给出动作相似度和建议,一旦用户摔倒,马上就会检测到。
彼时正值移动互联网创业,这样的“人体物联网”思路别具一格:中科院投入千万在类似的项目上,国外类似产品笨重低效却卖75万一套,智能硬件和健康一定会在未来成为风口。虽然有基于摄像头的类似设备Kinect,但它在阳光下完全不能工作,可XMove毫无压力。
如果能满足健身爱好者和舞蹈家的要求,我相信这套系统至少能赚个北京一套房(2011年二环内三万一平)。
超轻薄的动作传感器
因为要贴在人身上,所以传感器必须非常轻薄,我们选用了超小的CPU,加速度计和陀螺仪,用手工焊接出了50套微型节点(这样才够两个人嘛),成品只有4mm厚度,比手机常用的TF卡稍微大一些:
调试微型节点遇到了很大的困难:传感器数据总是读取失败!刚开始以为是硬件问题,重做了七八次电路,多花了几万块钱,电路板堆得有一米高,项目延期了接近半年!险些要放弃的我,最后在国外某篇文献里查到了答案。当时我疯了,冲出去大喊大叫!
如果你吐槽软件开发难,是因为不知道做硬件有多苦,焊接米粒一样的芯片,省吃俭用,而一不小心就能烧掉一个月的饭钱。遇到问题得靠大量的经验去解决,硬件工程师是用钱和汗水堆出来的,此话并不为过。
为了解决多个节点的无线通信和充电,我们设计了“节点航母”,它能最多同时与32个节点通信,把节点插在航母上就能充电,还能通过蓝牙把数据传给手机:
我还给XMove专门设计了一个手柄(下图最右),包含八个按键,两个摇杆,想想真丧心病狂。这是所有4代硬件的全家福:
然而,我们还是遇到了几乎无法解决的问题:无线通信。电池容量太小,当时的蓝牙2.0功耗太高,更高级的无线方案根本用不起。
我们自行设计了支持自动跳频,时隙划分,支持自动组网和路由,功耗低于2mA的通信协议:
管理端能够方便的监控每个节点的状态:
然而,成也萧何败萧何。当23个节点同时以32帧的速率传输数据时,信道质量变得出奇的差。无线芯片底层采用GFSK调制,而底层CRC校验错误一个字节,就会抛弃整个包。节点间干扰非常严重,发射功率太低,只要转身发生阻挡,丢包率90%以上!
我曾想通过数据平滑来对丢失数据做补偿,然而这么高的丢包率让一切方案变得束手无策。我们没有设计天线的经验,北邮在这个领域强手如林,我们寻遍各大实验室,大神给的方案都败在了功耗和成本上:那些方案几分钟内就会消耗完那可怜电池的所有电量。
Android版本的XMove
由于手机要作为信号中继,也是重要的传感器之一,XMove就肯定要涉及手机端。
2011年暑假,我就开发了这个安卓版本的XMove组件。下面是手机无线多点触摸板,支持双指缩放和三指拖拽,能与电脑通过WIFI和3G信号连接,这是使用截图:
安卓手机端的界面截图:
还有通过手机旋转和倾斜实现的飞行游戏手柄(著名的飞行战斗游戏HAWX):
我还专门针对安卓版本开发了一版PC管理器:
我通过XMove学会了安卓开发,那时安卓程序员还是凤毛菱角,赚钱超多,好后悔没有对安卓投入更多的精力。不过现在看来,安卓开发已经没落了,数据算法工程师反而独占鳌头。哈哈哈。
强大的监控端
为了能够监控不同节点,重建人体动作,我花了大量时间,开发了爬虫Hawk的祖奶奶,功能强大的监控软件XMove Studio:
你能对任意节点进行路由组网,远程配置,通过拖拽支持复杂的应用。它是Hawk的最初原型!
管理端能用3D形式展示数据流是如何从传感器传入到不同应用,并能监控各节点的信号强度,电量等关键信息:
也许你发现了,这套系统有过度设计的嫌疑。很多功能不重要,却浪费了过多时间,而最核心的算法部分,却没有分配足够的精力。
实现3D人体重建
可能你对上一篇文章中展示节点姿态的茶壶有印象。为了重建人体,就需要操控人体3D骨骼。我从头学了一遍OpenGL,一点点地研究四元数绑定,和矩阵变换,刚开始实现的效果是这样:
想想看一个在X光片里的骷髅跟着你来回乱动了,妹子们都表示太吓人了!我不得不放弃了这个OpenGL方案。
最后才用到了Unity3D,这个超强的3D引擎,配合我写的C#远程RPC(程序之间互相通信的协议),很好地解决了这一问题,效果还不错,搬运工森林旅游即视感:
不过因为丢包的问题,突然胳膊肘就拐到身后,大腿就撇到了头上:搬运工哥哥各种丧病的动作,把参观者笑个半死,哈哈哈哈哈。苦中作乐,苦中作乐!
加速度计,磁力计和陀螺仪的原始数据是不能直接给3D引擎用的,需要做传感器融合和姿态解算。当时AHRS(全姿态解算)找不到像样的资料,我不得不花了好多精力研究,这是当时演算的一部分手稿:
之前用SVM解决动作判别,但无法处理流式数据。因此我尝试用HMM(隐马尔科夫链)去监测奔跑跳跃,摔倒或挥手,还能分析它与标准动作的相似度,但效果总是不好。当时对步态识别能搞个八九不离十,更复杂的就搞不定了。现在想起来,低阶HMM无法根本解决它,而三年后才出现解决这类问题的算法LSTM(哭)...
从激情到放弃
XMove第四代,消耗的精力是前三代总和的接近两倍。虽获得了学校老师的帮助,不过经费基本自掏腰包。开发出两套原型机,在无干扰的环境下,能实现基本的动作捕捉,而一旦无线环境恶劣,通信问题就让整个系统乱套了。
当朋友们出门旅游玩耍,我却低头检查硬件问题;当同学们在各大名企实习,我在调动作识别算法。在实验室繁重的项目压力下,我还要在XMove上投入足够多的精力和资金。直到最后,它都没有商业化应用,雷声大雨点小,因为它太不稳定了。
曾经充满美好幻想的我,却看不到未来,终于在2012年的最后一天,我决定及时止损,出现了开头出现的那一幕。
究其失败原因:
严重的过度设计,一股脑地把所有的自己想到的需求塞进去,根本没有调研目标用户怎么想。
大量的精力投入到根本不是核心的监控端开发,却没有在动作捕捉算法上下足够功夫。
缺乏硬件经验:事先调研不足,对无线信道效率估计过高,适合我们的无线方案,直到2015年才出现。
这还仅仅是研发层面的困难,更不用说交付给用户后,电池老化,软件稳定性的问题:我们的硬件根本不可靠,渗进汗水可能就短路烧坏了。
因为XMove,我甚至开始怀疑面向对象编程。如果我现在写Python版本的XMove驱动和管理端,代码还是不会超过1000行,函数式风格,结构肯定会远好高于之前的设计。
我依然记得2012年的正月初一到初七,我拒绝了大部分的走亲访友,一个人在家憋着写代码;记得和队友一起,钻在实验室的焊接台下,检查着每一个焊点,之后只敢去食堂吃最便宜的菜;也记得因为无线通信不论如何都无法解决,气愤地在操场上大喊大叫。
不过,我不后悔。
我也记得它给我带来的兴奋和成绩。XMove在我大学和研究生阶段,写下了浓墨重彩的一笔。它驱使我解决一个个实际的问题,对架构有了嗅觉,能够随时警惕过度设计,知道了简洁远优于复杂的道理。也知道如何做合理的商业决策,避免因为自己的幻想,一条道走到黑。
XMove寿终正寝,但它依然以文章的形式出现在我的博客中。在Git Hub里也开源了它的部分代码。我给它装了一个精心设计的塑料盒,放在书房里。
这就是我和XMove的故事。
后记
- 据不完全统计,XMove在两年内占据了我50%以上的工作时间。
- XMove能同时兼容2012年上市的Kinect,并提供统一的API
- 笔者在之后金盆洗手,不接触任何硬件开发项目
- 2013年开始,智能硬件成为风口,大量类似产品出现,但之后浪潮退净,幸存者所剩无几