web 3d 与仿真
时间:2022-08-27 07:12:01 | 来源:网站运营
时间:2022-08-27 07:12:01 来源:网站运营
web进入3d时代的时间并不长,web在3d领域的发展却十分迅速。web 3d技术已经在房地产房型展示、博物馆艺术品或文物展示、电商平台的商品展示领域获得广泛应用。然而web 3d技术在仿真领域的应用却比较鲜见。
目前而言,3d仿真还是PC软件的天下,大部分仿真软件都会使用UE4或unity3d这样的重量级引擎,我司用的OGRE也是一款重量级引擎。以OGRE为例,其诞生于2000年左右,最后更新截至于2012年,ROS系软件RVIZ和gazebo都是使用OGRE开发。当初我司选用OGRE作为开发引擎,主要是因为希望能和C++无缝结合,开源,能够在ubuntu下运行,毕竟大部分人工智能算法投入生产后都是使用C++。
但是,基于一年的开发使用经验,OGRE的缺陷正在逐渐暴露出来,这是一个常年不更新的框架,一个与最新技术水平脱钩六年的框架,技术理念十分陈旧,资料也很匮乏。比如绘制凹凸的多边形,没有现成的类型可以使用,三角化算法没有集成,网上又很难找到案例。3D文字的绘制官方本身没有提供api,非官方提供的代码运行效率却又不佳。对3d对象的几何数据、空间节点和材质的管理是各自独立的,灵活性太高,方便性不足。单例、智能指针和普通指针混用,缺乏统一的风格。我把较多的时间花在弥补这些缺陷上,不能专心于仿真本身的设计。鉴于此,我向公司多次提出使用新的三维引擎,但是没有引起足够的重视。由于模拟器已经深度集成OGRE,重新使用新的三维引擎必然是伤筋动骨的,积重难返成为使用新技术的主要障碍。
传统意义上,使用C++代表着运行效率高,但是通过使用OGRE发现,C++运行效率高还有一个前提,就是写C++的人的水平也要高,指导怎么充分利用计算资源,并能设计出简单有效的框架。在我们小组内,我能设计出简单有效的框架,有人掌握丰富的C++技巧,但是没人知道怎么和底层紧密结合,所以我们的C++并没有高的运行效率,反而有时候运行很慢。所以如果做不到和底层紧密结合,还不如把这些工作交给开发三维引擎的人,因为他们花了大量的时间在研究这个。
基于我之前使用qml开发3d可视化软件和标注工具的经验,我萌生了一个想法,3d使用web开发仿真界面也未必不可行,如果公司在短时间内不能采用新的三维引擎,那么我可以先自行尝试一下使用web3d技术。
qml是什么?qml是qt公司力推的新UI框架qtquick的主要开发语言。qtquick是从web借鉴而来,qml则是从js衍生而来。其大体的原理是使用qml像html、css那样设计界面,像nodejs那样用C++作为和系统交互的语言,本质上与electron类似。我之前的工作中,因为喜欢新技术,threejs上手比较快,用qml嵌套canvas3d,集成了threejs构建3d场景,开发了一款实时显示的可视化的软件。尽管也存在运行效率的问题,但是已经颠覆我对脚本语言的看法。
脚本语言不仅可以开发大型的实时软件,并且拥有更高的开发效率,在没有软硬件通吃的3d开发人员的情况下,使用脚本语言开发3d软件也是一个不错的选择。
在我司,我承接了3d标注工具的开发。最开始,3d标注工具是打算用OGRE开发,而且网上那个已有案例。当时需求催的比较紧,本来是打算把已有的3d代码打包成比较通用的库之后,再开发,后来评估发现这样还不如重新写一个,因为当时的3d代码的通用性实在是太差了。于是我提出我曾经用threejs快速开发过3d软件,我可以再次使用threejs开发一个全新的标注工具。这样我花了一个月时间,用qml和threejs把他们要的3d标注工具开发了出来。这么开发还有一个好处,就是当标注人员越来越多的时候,标注工具需要web化,本来标准工具就是用threejs写的话,web化起来比较容易。
几个月过去后,我司成立了标注公司,标注需要大量的人,标注工具也需要web化了。于是之前的代码再次派上了用场。基于之前我使用过vue和element-ui,这次web化的时候我再次使用这两个框架。web开发和qml开发有所不同,web开发没有编译过程,调试可以在浏览器内完成,谷歌浏览器提供了强大的开发工具,能够所改即所见,dom组件对应代码,相比qt提供的工具来说方便了不少。而且直接使用web开发后,可以使用threejs的最新版本,功能没有限制,可以直接使用一些配套脚本,并且渲染效率有所提高。
本来我是想,所有功能都在前端完成,如果可能的话。但是我在开发过程中我发现了一个问题,就是前端无法获取本地的文件目录,这个只能在后端完成,后端使用什么语言,什么框架又成了一个问题。因为之前用过java和C++写过简单的服务器,所以我知道java过于重量级,而C++没有什么好的服务器框架。我想能不能使用websocket,因为websocket可以从后端主动发数据给前端,让前端实时显示,在数据播放的时候也可以做一些标注工作。于是我找到了websocketd,一个简单易用,并且支持多种的脚本的软件。这个软件本身就是一个可执行程序,可以通过命令行运行,参数设置为要执行的脚本即可,实在是比一个有一大堆需要学习的api的成熟框架要好用的多。而且这个时候我仅仅是需要用后端获取一下本地目录,这是一个很简单的需求。我已经学会了python,知道怎么用glob获取目录,所以python是后台脚本的第一选择。
我花大概一个月的时间将原有的qt开发的标注工具转化成了web软件,相比原版,web版的点云加载和点选速度更快,操作更简便,界面更现代化。其中点云加载和点选速度更快是我没有料想到的。因为qt不支持js读取文件所以原来是用C库加载的,而且我还因为大点云点选速度较慢对点云做了分割处理,就这样加载速度还不及后来直接用前端的js加载速度快,点选速度也不及后来没有分割的速度。需要指出的是,虽然后来的web版中我没有写算法分割,但是可能在使用的新版threejs的点云算法中已经做了分割。qt允许集成的threejs版本是74,而最新的threejs已经进化到了99,这之间的25个版本点云算法可能已经有了巨大的提升。至于加载速度,我有测过,加载时间主要在调用C库api的阶段,而后数据发到qml耗时并不长。而js加载点云是直接读文件,不存在语言之间的数据传递。所以js加载速度快本来就是情有可原的,并且可能在加载算法上还要优于我使用的C库。
讲了这么多,还是在web 3d上,和仿真没有产生关系,我前面提到websocket通信支持后端对前端主动发数据,那么只要网络够好,延迟够低,那么web也可以实现实时刷新。比如我们有一辆车在前端显示,那么后端不断的发送新的位姿数据,前端的车辆就会动起来。鉴于我正在开发车辆的动力学模型,正需要一个3d的显示界面,之前使用模拟器作为可视化工具时,把大量的时间花在怎么修改模拟器上,反而没多少时间调试模型,所以我使用之前标注工具的代码,将其改造成一个实时仿真工具。
这时候再用websocketd就不行了,因为websocketd不支持python脚本引用非标准库,就是使用numpy还行,使用pytorch这样的第三方库就不行了,所以有必要再找一个再复杂一点的框架。于是我开始搜索python的web框架,基本上就三个,DJango、Tornado和Flask。DJango是一个重型框架,Flask是一个微内核框架,而Tornado介于两者之间。在比较websocket方面的支持力度上,似乎只有Tornado是原生支持的,毕竟Tornado宣称的优点就是适应长连接。
对于仿真而言,最有趣的地方在于能够看到一个事物朝着自己预想的方向发展,如果没有可以通过各种方法找出问题所在。如果模型正确,还可以预测出未来的发展方向。对于我来说,我现在有一个python写的车辆模型,有一个显示车辆位姿的界面,如果在界面上加上一些输入控制参数的控件,那么可以在界面上实时观察到控制参数对车辆位姿的影响。由于python有ros的全套api,在后台接受ros消息驱动车辆行走也是可能的。
有了3d显示界面,还需要仿真控制按钮,开始、暂停、重置、是否加载神经网络模型,这些和simulink类似。我还需要曲线来显示车速和加速度,这也和simulink类似。在显示曲线上,我也头疼了一番,比较了echart,chartjs,这两个都是开源库,echart是国产的,百度出品,而chartjs是github上的开源库,相较而言,我更喜欢chartjs的国际范,chartjs社区相当活跃,有更多人使用的产品,其问题肯定更少。chartjs虽然没有专门的实时更新的例子,但是实现实时更新只是一句话的是,就是把dataset改了。
chartjs解决了而为曲线的显示问题,但是我在开发神经网络模型的时候需要显示3d的散点图,我最开始使用的是matplotlib,卡的一笔,而且没有交互功能,查询点的数据要自己写事件响应的代码,太麻烦,所以我在同事的推荐下使用plotly,结果没账号不能用,后来注册了账号还是不能用,我直接放弃了。接着我使用了一个开源的免费的竞品bokeh,同样是用python控制数据,前端显示数据,但是是生成一个离线网页,2d散点图用的很好,当我觉得就是你的时候,才知道这家伙不支持3d,后来想想也是web里2d和3d是两套不同的技术。绝望中我又想起了pytorch有一套自己的可视化工具visdom。
visdom和plotly和bokeh一样都是基于web的可视化框架。不同在于visdom是开源免费的,自带服务器程序,并且支持3d。其实visdom也是使用plotly的,估计付了费。但是visdom的用户不用付费。他的3d的api设计也十分人性化,可以直接渲染矩阵,2d和3d公用同一个散点图api,函数内部会自动判断矩阵的维数。visdom可以在一个页面内同事显示多个子窗口,布局管理是自动的,这个也为数据监控提供了极大方便,我可以拿visdom的默认界面作为我的仿真软件的数据监控界面。也就是说chartjs也可以不用了,直接在python后台发送数据就行。
大概总结一下,我所面临的问题是如何快速开发有3d显示界面的车辆动力学仿真软件。我的解决方案是使用web 3d+websocket+python。
python模型-tornado=>data via websocket=>threejs/chartjs
仿真的模型是用pytorch构建,车辆的运动学公式加上pytorch从数据中学习而来的表格构成了整个模型,然后tornado的定时事件中定时调用模型的步进函数,可以完全不依赖ros就能跑。
由于目前算法的调试还比较粗糙,仿真往往还只是逻辑验证的过程,发现算法中的流程或逻辑错误,还不能支持调参的需要。其中主要的问题是仿真和实际的差距还比较大。例如车辆的刹车距离和实际不一致,这个问题主要是因为车辆的实际加速度并不是控制指令发过来的加速度,这两者之间不是直接的等于关系,VCU在接受控制指令中的加速度和其他车辆状态信号后,会根据某种算法换算成变速器档位和油门或刹车信号等,这种算法对我们来说是黑盒的。这种情况下用传统的动力学公式建模并不是那么容易的事。所以我考虑到了使用机器学习方法,从数据中习得模型。