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的故事。

后记

  1. 据不完全统计,XMove在两年内占据了我50%以上的工作时间。
  2. XMove能同时兼容2012年上市的Kinect,并提供统一的API
  3. 笔者在之后金盆洗手,不接触任何硬件开发项目
  4. 2013年开始,智能硬件成为风口,大量类似产品出现,但之后浪潮退净,幸存者所剩无几

自述创业史 | XMove动作感应系统(二)的更多相关文章

  1. 光荣与梦想 | XMove动作捕捉系统(一)

    XMove是我和几个死党从2010年开始开发的一套人体动作捕捉系统,软硬件全部自行开发,投入了大量的精力,历经三年,发展四个版本. 今年春节回到老家,翻出了2011年春节时焊电路用过的松香和和硬盘角落 ...

  2. Win7系统安装Centos7.0双系统(二)

    4.6语言选择

  3. Epicor系统二次开发

    Epicor系统二次开发 一.获取或修改界面EpiDataView的字段数据(Get EpiDataView data) C# EpiDataView edv = (EpiDataView)oTran ...

  4. go语言打造个人博客系统(二)

    go语言打造个人博客系统(二)   在上篇文章go语言打造个人博客系统(一)中,我们了解了go语言的优点和go语言的数据库操作,本次我们会完成博客系统的后端开发. 博客系统后端接口开发 路由测试 ht ...

  5. UGUI的优点新UI系统二 直观、易于使用

    UGUI的优点新UI系统二 直观.易于使用   对于UI控件,开发者可以直接使用鼠标在Scene视图里编辑它们的大小.位置和旋转角度,而无需编写任何代码,以Button为例,如图1-3.图1-4和图1 ...

  6. (dede)织梦系统二次开发笔记

    (dede)织梦系统二次开发记录 --soulsjie 一.模板常用文件说明 模板文件都在文件夹templets下,我们以默认模板(default)为例,对模板文件结构进行分析: 首页模板文件目录 \ ...

  7. 亿级在线系统二三事-网络编程/RPC框架 原创: johntech 火丁笔记 今天

    亿级在线系统二三事-网络编程/RPC框架 原创: johntech 火丁笔记 今天

  8. C#开发PACS医学影像处理系统(二):界面布局之菜单栏

    在菜单栏布局上,为了使用自定义窗体样式和按钮,我们需要先将窗体设置为无边框,然后添加一个Grid作为菜单栏并置顶,VerticalAlignment="Top" logo图片和标题 ...

  9. 通过Dapr实现一个简单的基于.net的微服务电商系统(二)——通讯框架讲解

    首先感谢张队@geffzhang公众号转发了上一篇文章,希望广大.neter多多推广dapr,让云原生更快更好的在.net这片土地上落地生根. 目录:一.通过Dapr实现一个简单的基于.net的微服务 ...

随机推荐

  1. hibernate---树状映射

    总公司--分公司1, 分公司2 分公司1: 分公司1下部门1, 分公司1下部门2 分公司2: Org.java: package com.bjsxt.hibernate; import java.ut ...

  2. typedef和block

    为block类型对象取别名 1.没有使用typedef的情况 int (^block_add)(int, int) = ^(int value1, int value2) { return value ...

  3. 51nod1138(math)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1138 题意:中文题诶- 思路:假设 x=a1+(a1+1)+ ...

  4. ice grid 完整部署过程

    待补充 一 理论准备 一个IceGrid集群有一个registry(注册表,用于定位)和多个node组成. IceGrid配置包括集群配置和应用配置: config.grid是集群配置,配置Regis ...

  5. STL中的所有算法(70个)

    STL中的所有算法(70个)----9种类型(略有修改by crazyhacking) 参考自: http://www.cppblog.com/mzty/archive/2007/03/14/1981 ...

  6. POJ 2139 Six Degrees of Cowvin Bacon

    水题,Floyd. #include<cstdio> #include<cstring> #include<algorithm> using namespace s ...

  7. mysql 大树据表update很慢

    问题描述: 数据表千万量级,update  where gid="adadfadsfasdf",返回结果显示耗时70ms到1s之间 分析: 表很大,那么update,可能先要取索引 ...

  8. 内层div的margin-top影响外层div——引出外边距合并Collapsing margins

    内层div的margin-top影响外层div——引出外边距合并Collapsing margins 作者:zccst 今天才算是了解边距合并.正如一位前辈所言,每一个CSS的坑,都让你学到不少知识. ...

  9. doxygen 生成源码文档

    使用doxygen 生成源代码的文档是相当方便的,本文就简单整理下doxygen的使用说明 1. 安装 关于安装的问题不做特殊的说明,这里直接使用命令安装, 源码安装不做介绍 ubuntu: sudo ...

  10. NOIP前刷水行动

    2016.11.15 BZOJ1009:DP+矩阵乘法+KMP BZOJ1898:矩阵乘法 BZOJ4101:贪心,考虑我们往右边撞的时候,我们会向左边冲 ,于是枚举答案点利用一个指针计算即可! 20 ...