android 电阻单点触摸屏校准
[复制链接]
今天做了android校准下触摸屏,注意触摸屏可能不同,我们目前使用单点电阻是触摸屏,android 平台是 2.1
以下是触摸屏校准
client 采集数据:计算校对系数,写入文件 /data/etc/xxxx通过propty来设置状态 InputDevice.java 根据propty 读取校对系数校对数据。
采用校对数据模型 M=ax by k1;N=cx dy k2,其中 M,N计算校对系数后的准确触摸屏位置。
所以我们要做的是通过数据收集来计算a,b,k1,c,d,k2.每个维度的坐标都有三个系数,所以我们收集三个有效的数据点。
M1=ax1 by1 k1 ; N1=cx1 dy1 k2
M2=ax2 by2 k1 ; N2=cx2 dy2 k2
M3=ax2 by2 k1 ; N3=cx2 dy2 k2,其中(M1,N1),(M2,N2),(M3,N3)是您校对的标准数据,在我的代码中提取
上角(32,32)(SCREEN_WIDTH-右脚(32,32)SCREEN_HEIGHT-32),
(x1,y1),(x2,y2),(x3,y3)在校准前分别获得 触摸屏的数据。
然后可以解决a,b,k1,c,d,k2.让这六个数据写入/data/et/xxx文件中。
然后InputDevice.java读取propty决定是否使用校对系数的状态.。
触摸屏设置后,设置为done
当InputDevie 发现propty为done的时候读取校对系数建立校对模型。
来自触摸屏的数据(x,y),然后由公式,X准=ax by k1; Y准=cx dy k2; 试验证准有效
代码分析:
界面代码 TouchCalibration.java,很简单,全屏activty
模型M的取值范围
int xList[] = {
32, UI_SCREEN_WIDTH - 32, 32, UI_SCREEN_WIDTH - 32, UI_SCREEN_WIDTH / 2
};
模型N的取值范围
int yList[] = {
32, 32, UI_SCREEN_HEIGHT - 32, UI_SCREEN_HEIGHT - 32, UI_SCREEN_HEIGHT / 2
};
事实上,五个参考点的坐标只用了三个点,哈哈(我还没有理解五个点的数学模型。如果我知道,我希望我能给你一些建议)
重载 onTouchEvent接口,然后移动三点实际接触的坐标
x1,y1,x2,y2,x3,y3.这个准确的位置分别对应xList[0],yList[0],xList[1],yList[1],xList[2],yList[2],
取道数据后,使用Calibrate.java来计算出 a,b,k1,c,d,k二、三个未知数三个方程求解,
主要函数在perform_calibration 中
a=((y3-y2)*(M2-M1)-(M3-M2)*(y2-y1))/((y3-y2)*(x2-x1)-(y2-y1)*(x3-x2))
其他的可以自己计算,
float M1,M2,M3,N1,N2,N3;
float a,b,k1,c,d,k2;
float x1,y1,x2,y2,x3,y3;
float mul,div;
float scaling = (float)65536.0;
M1=cal.xfb[0];
N1=cal.yfb[0];
M2=cal.xfb[1];
N2=cal.yfb[1];
M3=cal.xfb[2];
N3=cal.yfb[2];
x1=cal.x[0];
y1=cal.y[0];
x2=cal.x[1];
y2=cal.y[1];
x3=cal.x[2];
y3=cal.y[2];
div=((y3-y2)*(x2-x1)-(y2-y1)*(x3-x2));
mul=((y3-y2)*(M2-M1)-(M3-M2)*(y2-y1));
a=mul/div;
div=((x3-x2)*(y2-y1)-(x2-x1)*(y3-y2));
mul=(x3-x2)*(M2-M1)-(x2-x1)*(M3-M2);
b=mul/div;
k1=M1-a*x1-b*y1;
div=((y3-y2)*(x2-x1)-(y2-y1)*(x3-x2));
mul=((y3-y2)*(N2-N1)-(N3-N2)*(y2-y1));
c=mul/div;
div=((x3-x2)*(y2-y1)-(x2-x1)*(y3-y2));
mul=(x3-x2)*(N2-N1)-(x2-x1)*(N3-N2);
d=mul/div;
k2=N1-c*x1-d*y1;
Log.d("[hd debug]",a ":" b ":" k1 ":" c ":" d ":" k2 ":");
cal.a[0]=(int)(a*scaling);
cal.a[1]=(int)(b*scaling);
cal.a[2]=(int)(k1*scaling);
cal.a[3]=(int)(c*scaling);
cal.a[4]=(int)(d*scaling);
cal.a[5]=(int)(k2*scaling);
cal.a[6]=(int)(scaling);
return true;
然后在文件//data/etc/pointercal中,并设置ts.config.calibrate propty为done,
ts.config.calibrate propty是InputDevice.java,与触摸校对程序的通信标志。
InputDevice.java 中修改你的generateAbsMotion函数,据说android 2.支持多点触摸,我们使用电阻式,所以没有调查。
(我没有看懂)InputDevice.java代码,修改generateAbsMotion只能满足我的项目需求,请仔细考虑。
String prop = SystemProperties.get("ts.config.calibrate", "noset");
if (prop.equalsIgnoreCase("start")){
Log.d("XXW prop", prop);
Log.d("XXW", "prop.equalsIgnoreCase start");
device.tInfo = null;
}else if (prop.equalsIgnoreCase("done")){
Log.d("XXW prop", prop);
Log.d("XXW", "prop.equalsIgnoreCase done");
readCalibrate();
device.tInfo=tInfo;
SystemProperties.set("ts.config.calibrate", "end");
}else{
Log.d("XXW prop", prop);
Log.d("XXW", "prop.equalsIgnoreCase else");
}
这里根据propty是否使用校准系数,
若采用,则采用隐射模型:
if (absX != null) {
if (device.tInfo != null){
reportData[j MotionEvent.SAMPLE_X] = (device.tInfo.x1 * x device.tInfo.y1 * y device.tInfo.z1);
}
}
if (absY != null) {
if (device.tInfo != null){
reportData[j MotionEvent.SAMPLE_Y] = (device.tInfo.x2 * x device.tInfo.y2 * y device.tInfo.z2);
}
}
计算新的坐标,
代码的资源中给出代码,有兴趣的同学自己实现,没兴趣的同学花点分,下载资源代码也可以。