我的一个同事自定义了一个控件,控件代码如下:
public class CustomTextView extends TextView implements OnClickListener, OnFocusChangeListener { public CustomTextView(Context context) { super(context); init(context); } public CustomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { setTextSize(context.getResources().getDimension(R.dimen.dimen_30sp)); setOnClickListener(this); setOnFocusChangeListener(this); } @Override public void onClick(View v) { } @Override public void onFocusChange(View v, boolean hasFocus) { } }
定义控件的时候,控件的文本大小定义成了30sp,为了适配考虑,30sp从dimens.xml文件里面获取。当时写这个控件时,屏幕分辨率为320x480,密度为160dpi,30sp=30dp=30px,后来需要适配480x640的分辨率,密度为240的屏幕,这时候30sp=30dp=45px。
但结果大大出乎我们意料,240dpi的屏幕,这个控件的字体不是45px,而是67.5px,显然不符合我们的要求。其中一个同事折腾了很久,向我请教,于是我怀疑setTextSize函数是不是做了什么手脚,于是查看源码,恍然大悟:
/** * Set the default text size to the given value, interpreted as "scaled * pixel" units. This size is adjusted based on the current density and * user font size preference. * * @param size The scaled pixel size. * * @attr ref android.R.styleable#TextView_textSize */ @android.view.RemotableViewMethod public void setTextSize(float size) { setTextSize(TypedValue.COMPLEX_UNIT_SP, size); } /** * Set the default text size to a given unit and value. See {@link * TypedValue} for the possible dimension units. * * @param unit The desired dimension unit. * @param size The desired size in the given units. * * @attr ref android.R.styleable#TextView_textSize */ public void setTextSize(int unit, float size) { Context c = getContext(); Resources r; if (c == null) r = Resources.getSystem(); else r = c.getResources(); setRawTextSize(TypedValue.applyDimension( unit, size, r.getDisplayMetrics())); }
我们再看applyDimension函数:
public static float applyDimension(int unit, float value, DisplayMetrics metrics) { switch (unit) { case COMPLEX_UNIT_PX: return value; case COMPLEX_UNIT_DIP: return value * metrics.density; case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; }
原来setTextSize函数对应的单位本身就是sp。如果在240密度下,30sp=45px,setTextSize函数内部还需要乘以一个scaleDensity,那么setTextSize(30sp)实际设置的大小为30spx1sp=45x1.5=67.5px。
所以在做自定义控件的时候,设置控件文本大小的时候需要小心,否则搞了半天也找不到问题的症结所在。
在ubuntu下可以使用xrandr来设置自己需要的分辨率。大致步骤如下:
1.使用xrandr命令查看屏幕分辨率,这里我使用的是显示器(LVDS1),分辨率为1366*768
2.使用cvt命令生成一个新的modeline
3.新建一个分辨率模式
4.将新建的分辨率模式添加到显示器上
5.应用新的分辨率模式
0. 地图匹配的必要性
1. 位置地图匹配需要哪些 因素
2. 位置与地图匹配的算法
3. 位置与地图匹配的精度概率等分析
0. 必要性
GPS的Position只是一个数据,还需要与Map的Match,即由GPS坐标转换为地图坐标。不仅要找到地图上位置,还要找出地图上哪些道路与此位置最为接近,利用地图中结构化的模型(如道路,交点等)进行描述当前的位置。
GPS在与其他传感器数据融合,及经过卡曼滤波校正后,仍有有一定的误差,至少其卡曼滤波校正后其系统误差仍有 10-50m,一个好的匹配算法 能 依据GPS和其他传感器信息,结合地图中的结构信息(如道路),有95%的概率将真实误差缩小到5m内(不同的引擎,这个指标可能不同,需要根据实际情况进行考证)。
1. 因素
当前的车辆或GPS位置的状态,在道路上行驶,停车,货运(gps可用,传感器不应该使用),离开道路,不确定状态。
GPS位置信息、速度、角速度信息、曲率半径(数据来源?)
获取地图的数据接口
2. 算法步骤
a. 计算当前gps位置,利用前一状态和速度,偏转速度信息,进行估计计算。普通的线性运算。
b.计算当前方向,利用前一状态和传感器(角速度),进行估计计算。普通的线性运算。
c. 计算匹配的可能的位置,采用逐步匹配的方式
载入地图数据,获取结构化的道路信息pathId,计算长度和其包含的坐标点
计算候选的道路的位置和结构,利用道路长度和到道路终点距离计算当前位置offset,计算当前位置与起始点的方向、坡度、上下平坦程度。offset地图供应商会提供计算的接口。这个需要依据不同的状态,采用不同的算法,如停车、货运(拖车)、道路行驶,需用不同的数据。
计算估计的地图位置和方向(道路的offset和dir),以及其与GPS融合数据的真实位置距离和方向差。
计算各个候选道路的 属性类型,即将地图中道路的属性转换为 导航引擎的类型。更新道路匹配的状态。
d. 计算各个位置匹配的质量,分析 (非常重要)
这个要依据道路的场景分别进行计算。首先计算偏差:
GPS位置与道路的距离差
GPS方向与道路的方向差
各种道路场景,不同的场景,偏差在匹配中的权重也不同
* 环岛
距离差的比重比较大。即方向较准确,而距离较不准
道路与车辆的距离差*2、方向差.
如果是入口,行驶区域,match的程度减半,非机动区域匹配程度增加
出口:一般的计算方式,当时行驶区域,偏差程度翻倍,行驶区域减半
一般的计算方式: 偏差角度+距离*2 (+ lackmeter)
* 蛇形蜿蜒的
距离偏差的重要程度大大下降,然后加上方向偏差即可
* 重要隧道
当候选道路多于一个时,采用普通计算方式
只有一个时,蛇形计算方式
* 离开道路
无匹配
* 正常的
一般的计算方式
道路开始段:同下
道路结束段:距离,角度的偏差,不过要乘以系数,而且十字路口,且未来转角<90度时,角度偏差减半
* U型道
距离差*2
当toEnd为负数时,偏差加大。若offset为负数,同样加大偏差。
匹配程度计算:
根据偏差数据,可以计算匹配程度。一般情况下,两者呈线性关系(负数)。
e. 启发式进行计算
主要是计算坡度,里程与匹配程度的关系。
f. 计算匹配的模式
更新匹配的模型,由先前道路的模式,加上计算的匹配值,确定是否将模式设置为sure 或unsure或不变。
g. 排序
快速排序法,排序的依据是(匹配质量)
3. 匹配误差的量化计算?
影响因素:
地形/道路形状
当前GPS、sensor数据与道路结构化数据的距离、方向差
当前GPS位置的状态是否稳定
就是上面位置地图匹配的算法。