学习收获点滴记录
2015.12.23
http://blog.chinaunix.net/uid-26694208-id-3184442.html
所要解决的问题:你根据经验的预测值(系统的预测值)和温度计的值(测量值)。下面我们要用这两个值结合他们各自的噪声来估算出房间的实际温度值。
首先,我们先要引入一个离散控制过程的系统。该系统可用一个线性随机微分方程(Linear Stochastic Difference equation)来描述:
X(k)=A X(k-1)+B U(k)+W(k)
再加上系统的测量值:
Z(k)=H X(k)+V(k)
上两式子中,X(k)是k时刻的系统状态,U(k)是k时刻对系统的控制量。A和B是系统参数,对于多模型系统,他们为矩阵。Z(k)是k时刻的测量值,H是测量系统的参数,对于多测量系统,H为矩阵。W(k)和V(k)分别表示过程和测量的噪声。他们被假设成高斯白噪声(White Gaussian Noise),他们的covariance分别是Q,R(这里我们假设他们不随系统状态变化而变化)。
5个重要的方程:(具体见链接博客)
预测: X(k|k-1)=A X(k-1|k-1)+B U(k)……….. (1)
最小均方差: P(k|k-1)=A P(k-1|k-1) A’+Q……… (2)
修正预期值: X(k|k)= X(k|k-1)+Kg(k) (Z(k)-H X(k|k-1)) ……… (3)
卡尔曼增益: Kg(k)= P(k|k-1) H’ / (H P(k|k-1) H’ + R) ……… (4)
下一时刻参数:P(k|k)=(I-Kg(k) H)P(k|k-1)……… (5)
小结:系统控制过程存在误差,测量过程也存在误差,噪声无法避免,在动态控制过程中,如何在预测参数和测量参数中,实现最优化的结果,卡尔曼滤波给出了方案。这一方法尽可能地让得到的结果和真实值相同,不仅可以避免噪声的干扰,还在一定程度上修正预测误差。
就是在给的参数中,确定卡尔曼增益Kg,然后最优化的计算,得到当前结果(最接近真实的结果),并结合当前结果,给定下一时刻的参数,虽在相邻两个时间点相关,但与起点无关。
重点在于怎样确定KG这个参数,怎样的算法才能让计算得到的结果最接近真实的结果。卡尔曼,已给出了答案。X(k|k)= X(k|k-1) + Kg(k)*(Z(k)-H X(k|k-1))
当前真实(最优化)值=预测的当前时刻的预测值+Kg*(系统的当前测量值-预测值)。
现在的难点在于,实际中卡尔曼增益Kg的求取,涉及矩阵,随机信号,MATLAB等的学习。要对矩阵、转移矩阵等的理解,还需要更多的时间。
设想:编写卡尔曼滤波算法,在实时检测温度、速度、高度、加速度等控制系统上,将对控制更加精确。
@ 通过MFC定时器应用实例(其他,Windows API函数使用定时器)
http://www.jizhuomi.com/software/232.html
1.创建基于对话框的工程
文件-项目-vc++->MFC应用程序-选择窗体参数,‘基于对话框’‘在静态库中使用’‘生成DLG类’。添加控件-在工具箱;查看代码-在解决方案;修改属性-在右键“属性”打开;在“caption”进行名字名字的修改;
未能实现定时器的应用,关于c++的继承、多态、虚函数等需要多学习才行!
@函数名: strstr 函数原型:extern char *strstr(char *str1, char *str2);
功能:找出str2字符串在str1字符串中第一次出现的位置(不包括str2的串结束符)。 返回值:返回该位置的指针,如找不到,返回空指针。
@strncpy 定义于 string.h,char *strncpy(char *dest, const char *src, int n),把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。(int n可用sizeof(str)-1代替)
@fprintf是C/C++中的一个格式化写—库函数,位于头文件<stdio.h>中,其作用是格式化输出到一个流/文件中;函数原型为int fprintf( FILE *stream, const char *format, [ argument ]...),fprintf()函数根据指定的格式(format)向输出流(stream)写入数据(argument)。
@memcpy函数:c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
函数原型:void *memcpy(void *dest, void *src, unsigned int count);
用法:(1)可以拷贝任何类型的对象,因为函数的参数类型是void*(未定义类型指针),也就是说传进去的实参可以是int*,short*,char*等等,
但是由于函数拷贝的过程是一个字节一个字节的拷贝的,所以实际操作的时候要把void*强制转化为char*,这样在指针加的时候才会保证每次加一个字节
@fscanf()函数(有点像正则表达式)功 能:从一个流中执行格式化输入,fscanf遇到空格和换行时结束,注意空格时也结束。
用 法:int fscanf(FILE *stream, char *format,[argument...]);
@feof()这个函数是用来判断指针是否已经到达文件尾部的。 若fp已经指向文件末尾,则feof(fp)函数值为“真”,即返回非零值;否则返回0。
@int fseek(FILE *stream, long offset, int fromwhere);函数设置文件指针stream的位置。
如果执行成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置,函数返回一个非0值。
实验得出,超出文件末尾位置,还是返回0。往回偏移超出首位置,返回-1,且指向一个-1的位置,请小心使用。
fseek函数和lseek函数类似,但lseek返回的是一个off_t数值,而fseek返回的是一个整型。
@size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
注意:这个函数以二进制形式对文件进行操作,不局限于文本文件
返回值:返回实际写入的数据块数目
(1)buffer:是一个指针,对fwrite来说,是要获取数据的地址;
(2)size:要写入内容的单字节数;
(3)count:要进行写入size字节的数据项的个数;
(4)stream:目标文件指针;
(5)返回实际写入的数据项个数count。
@枚举类型Enum在C语言等计算机编程语言中是一种构造数据类型[1] 。它用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型。Enum . C中示例:
typedef enum {
DEMO_LABEL_A = 0,
DEMO_LABEL_B,
DEMO_LABEL_C
DEMO_LABEL_D
} demo_label_t;
@最全ASCII码对照表
@0x00DA1525 处有未经处理的异常(在Proj_MIUData.exe 中): 0xC0000005:读取位置 0x00000004时发生访问冲突。
0xC0000005错误通常是由于内存访问错误引起,可能是你的程序有错误的指针操作或者访问了空对象;使用了未创建(未分配内存空间)的变量或对象。
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。
这类提示说明访问了非法的指针,可能是指针未初始化引起的。使用调试模式运行,在弹出提示框时选择中断,然后使用调用堆栈辅助,可以很好的地位到非法访问的指针的情况。
这类问题的答案之一~因为还可能是安装其他软件造成动态库冲突,也会出现这类问题。
我的问题思路:可能是不完整帧造成的;可能是对x这变量没有控制好。
@2015.12.31对bin文件进行操作,最后得到了成功结果,开心。