四旋翼调试日记(3)——上位机
上位机是所有在线实时系统监测调试仿真必不可少的一个环节,它不仅可以实现在线监测,并且可以嵌入算法以及调用诸如Matlab等仿真软件生成的DLL进行在线仿真计算,以及三维重现等可视化功能,因此在四旋翼调试过程中自然也不能少了上位机。
能够编写上位机的语言非常多,常用的如C++,C#,JAVA,VB,Labview,Delphi,Qt等等。相对而言C#和Labview上手容易,只要有面向对象的编程基础基本上可以毫无障碍地上手,因此我最终选择了C#,因为早在做智能车时期就已经玩腻了Labview,相对于C#而言,Labview其实就是一套引出了接口的可视化编程环境,灵活度并不高,当然,其对NI的硬件支持使得Labview在自动化测控领域也占有了相当的份额。
几乎所有的C#初学者都会感叹于C#的方便简单,然而事实上在深入学习之后会发现C#的学习 曲线刚好和C++相反,上手及其容易,要想深入乃至精通,其实是非常难的,不过对于我们这些想要写一些不是特别复杂的程序的程序员而言,C#绝对是神器。不过C#的程序效率是无法和C++相提并论的,毕竟在大多数情况下,非托管代码和托管代码比,在效率上还是有较大的优势的,但这并不能阻止C#的流行,通常可以使用C++写算法,引出接口,使用C#调用。另一方面,微软提出,当前C#下的DirectX开发的3D程序效率已经和C++十分接近,且XNA游戏开发基本上以C#为主,所以个人还是比较看好C#。此外,在移动端的开发,C#依然占有一定的市场,如WP,虽然当前的手机端被IOS与Android所统治,但我们还是应该以批判地眼光去审视其发展问题,由于JAVA学习成本较低,大量的软件类本科生跟风学习,Android开发的岗位需求日渐饱和,相比而言,IOS开发则成本高的多,并且上手难度也较大,至于其前景,则不好说,毕竟IOS是一个基于UNIX的系统,其收费性质和封闭性使得其发展速度开始跟不上基于Linux的Android了,当然,这些都是题外话了。
上位机的主要功能分为六大块:通信,协议,控制,显示,分析,仿真,重构。
1)通信作为软件的根基,如果通信的部分处理的不好,那么整个软件的所有功能都将成为**肋,因此,我们就很有必要对通信部分进行多线程处理,在这里可以使用线程池的方式处理。这里只使用了串口通信,至于TCP/UDP等网络通信方式也是大同小异的,不同之处在于协议。在串口接收事件中进行数据包的解码,之后开辟一个工作者线程,在该线程中进行数据处理,显示,分析等等,需要注意的是跨线程操作控件时需要进行委托,此外,尽量避免数据的线程同步问题。不同于传统的单线程编程模式,多线程编程中经常会出现意想不到的问题,如死锁,多线程的逻辑错误往往是始料未及的。
2)原以为协议会比较简单,然而实际上,写一个完整的协议事实上是十分蛋疼的,尤其在整个四旋翼系统需要不同的控制信号时,那么每个数据帧的长度可能会有所不同,因此,我针对了这种变帧长的数据帧进行了编码和解码的协议编写,基本的帧结构为以两个字节作为帧头来区分不同的数据帧同时用两个字节来表示帧长度,通过将串口缓冲区的数据转移到数组列表中(类似队列),通过索引帧头,帧长度的方式填充缓冲区以此来得到帧数据,经验证,该协议在一定程度上具有自校正能力,即进行了一定的纠错。
3)显示部分主要分为图像显示和波形显示。图像显示的功能主要为显示RGB565格式的彩色图像(OV7670摄像头的图像格式)以及8位灰度图(0V7620摄像头的图像格式),设计的初衷是便于显示航拍图像。至于波形显示,则是必不可少的了,在调试过程中,可以将诸如角度信息,PID的各项信息进行波形显示,有针对性地进行分析,并且程序能够自动对波形数据进行最值与极值点进行标注显示。同时,波形数据对为理论分析也提供了大量的依据。
4)控制部分主要分为四轴解锁上锁,写入PID参数以及期望角度的改变,同时在接收到下位机的ACK信号之后进行相关的显示。
5)重构。这里的重构指的是三维姿态显示,最初采用的是OPENGL,在.NET环境下,主要有SharpGL和CSGL,然而由于微软的DirectX和OPENGL一直处于竞争关系,因此C#对于OPENGL的支持十分的不友好,效率低下,于是我转用C++写OPENGL程序,效率可以,然而导入C#程序却十分困难,最后只能写成2个程序,在C#中通过调用进程的方式处理,显然,这样十分别扭,于是,我不得不放弃了OPENGL,转而使用微软的DirectX,花了几天时间初步学习了一下DirectX,发现用C#写DirectX程序还是十分简便的,效率也不低,于是又花了半天学了下3DMAX,做了一个四旋翼的三维模型,简单的渲染之后就可以用DirectX导入了,至于之后的旋转,平移这些运动对于DirectX来说也是小菜一碟了。 |