码迷,mamicode.com
首页 > 其他好文 > 详细

sensor:gsensor的流程以及优化分析

时间:2015-04-27 21:51:10      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:gesnor   优化   旋转速度   

概述

frameworks\base\core\java\android\view\WindowOrientationListener.java

监听sensor是否有数据变化

 

首先看看芯片方向(x,y,z):

技术分享

补充流程:

PhoneWindowManager调用updateOrientationListenerLp去SensorManager里面去注册一个Listener,

当Sensor发生变化的时候,PhoneWindowManager就可以监听到并且调用回调onProposeRotationChanged

Callback 如下:

1 MyOrientationListener.onProposeRotationChange  PhoneWindowManager.java

-------------

    class MyOrientationListener extends WindowOrientationListener {

       

        @Override

        public void onProposedRotationChanged(introtation) {

            if (localLOGV) Log.v(TAG,"onProposedRotationChanged, rotation=" + rotation);

            updateRotation(false);

        }

    }

--------

2. PhoneWindowManager.updateRotation(booleanalwaysSendConfiguration)

    void updateRotation(booleanalwaysSendConfiguration) {

        try {

            //set orientation on WindowManager

            mWindowManager.updateRotation(alwaysSendConfiguration, false);、、WindowManagerService的对象

        } catch (RemoteException e) {

            // Ignore

        }

    }

3. WindowManagerService.updateRotation(booleanalwaysSendConfiguration, boolean forceRelayout)

 

 

二代码分析

public void onSensorChanged(SensorEvent event) {

            // The vector given in theSensorEvent points straight up (towards the sky) under ideal

            // conditions (the phone is notaccelerating).  I‘ll call this up vectorelsewhere.

            float x =event.values[ACCELEROMETER_DATA_X];

            float y =event.values[ACCELEROMETER_DATA_Y];

            float z =event.values[ACCELEROMETER_DATA_Z];

 

            if (LOG) {

                Slog.v(TAG, "Rawacceleration vector: "

                        + "x=" + x +", y=" + y + ", z=" + z

                        + ",magnitude=" + FloatMath.sqrt(x * x + y * y + z * z));

            }

 

            // Apply a low-pass filter to theacceleration up vector in cartesian space.

            // Reset the orientation listenerstate if the samples are too far apart in time

            // or when we see values of (0, 0,0) which indicates that we polled the

            // accelerometer too soon afterturning it on and we don‘t have any data yet.

            final long now = event.timestamp;

            final long then =mLastFilteredTimestampNanos;

            final float timeDeltaMS = (now -then) * 0.000001f;

            final boolean skipSample;

            if (now < then

                    || now > then +MAX_FILTER_DELTA_TIME_NANOS

                    || (x == 0 && y ==0 && z == 0)) {

                if (LOG) {

                    Slog.v(TAG, "Resettingorientation listener.");

                }

                reset();

                skipSample = true;

            } else {

                final float alpha = timeDeltaMS/ (FILTER_TIME_CONSTANT_MS + timeDeltaMS);

                x = alpha * (x -mLastFilteredX) + mLastFilteredX;

                y = alpha * (y -mLastFilteredY) + mLastFilteredY;

                z = alpha * (z -mLastFilteredZ) + mLastFilteredZ;

                if (LOG) {

                    Slog.v(TAG, "Filteredacceleration vector: "

                            + "x=" +x + ", y=" + y + ", z=" + z

                            + ",magnitude=" + FloatMath.sqrt(x * x + y * y + z * z));

                }

                skipSample = false;

            }

            mLastFilteredTimestampNanos = now;

            mLastFilteredX = x;

            mLastFilteredY = y;

            mLastFilteredZ = z;

 

            boolean isAccelerating = false;

            boolean isFlat = false;

            boolean isSwinging = false;

            if (!skipSample) {

                // Calculate the magnitude ofthe acceleration vector.

                final float magnitude =FloatMath.sqrt(x * x + y * y + z * z);

                if (magnitude <NEAR_ZERO_MAGNITUDE) {

                    if (LOG) {

                        Slog.v(TAG,"Ignoring sensor data, magnitude too close to zero.");

                    }

                    clearPredictedRotation();

                } else {

                    // Determine whether thedevice appears to be undergoing external acceleration.

                    if(isAccelerating(magnitude)) {

                        isAccelerating = true;

                       mAccelerationTimestampNanos = now;

                    }

 

                    // Calculate the tiltangle.

                    // This is the anglebetween the up vector and the x-y plane (the plane of

                    // the screen) in a rangeof [-90, 90] degrees.

                    //   -90 degrees: screen horizontal and facingthe ground (overhead)

                    //     0 degrees: screen vertical

                    //    90 degrees: screen horizontal and facingthe sky (on table)

                    final int tiltAngle = (int) Math.round(//关键数据1tiltAngle  计算出传感器的倾斜角

                            Math.asin(z /magnitude) * RADIANS_TO_DEGREES);

                    addTiltHistoryEntry(now, tiltAngle);

 

                    // Determine whether thedevice appears to be flat or swinging.

                    if (isFlat(now)) {

                        isFlat = true;

                        mFlatTimestampNanos =now;

                    }

                    if (isSwinging(now,tiltAngle)) {

                        isSwinging = true;

                        mSwingTimestampNanos =now;

                    }

 

                    // If the tilt angle is tooclose to horizontal then we cannot determine

                    // the orientation angle ofthe screen.

                    if (Math.abs(tiltAngle)> MAX_TILT) {

                        if (LOG) {

                            Slog.v(TAG,"Ignoring sensor data, tilt angle too high: "

                                    +"tiltAngle=" + tiltAngle);

                        }

                       clearPredictedRotation();

                    } else {

                        // Calculate theorientation angle.

                        // This is the anglebetween the x-y projection of the up vector onto

                        // the +y-axis,increasing clockwise in a range of [0, 360] degrees.

                        int orientationAngle = (int) Math.round(//关键数据2计算出方向 角度

                                -Math.atan2(-x,y) * RADIANS_TO_DEGREES);

                        if (orientationAngle < 0) {

                            // atan2 returns[-180, 180]; normalize to [0, 360]

                            orientationAngle +=360;

                        }

 

                        // Find the nearestrotation.

                        int nearestRotation = (orientationAngle+ 45) / 90;

//关键数据3:计算出要旋转的方向;也就是说orientationAngle 需要大于45 才会找到一个方向(共四个方向:0,1,2,3

                        if (nearestRotation ==4) {

                            nearestRotation =0;

                        }

 

                        // Determine the predicted orientation. 判断预报的方向:mPredictedRotation是否合理

                        if (isTiltAngleAcceptable(nearestRotation,tiltAngle)

                                && isOrientationAngleAcceptable(nearestRotation,

                                       orientationAngle)) {

                            updatePredictedRotation(now, nearestRotation);

                            if (LOG) {

                                Slog.v(TAG,"Predicted: "

                                        +"tiltAngle=" + tiltAngle

                                        +", orientationAngle=" + orientationAngle

                                        +", predictedRotation=" + mPredictedRotation

                                        +", predictedRotationAgeMS="

                                               + ((now - mPredictedRotationTimestampNanos)

                                                       * 0.000001f));

                            }

                        } else{////所以做好不要进入 无效数据范围

                            if (LOG) {

                                Slog.v(TAG,"Ignoring sensor data, no predicted rotation: "

                                        +"tiltAngle=" + tiltAngle

                                        +", orientationAngle=" + orientationAngle);

                            }

                           clearPredictedRotation();

                        }

                    }

                }

            }

 

            // Determine new proposedrotation.判断新的建议的方向:mProposedRotation 是否合理

            final int oldProposedRotation = mProposedRotation;

            if (mPredictedRotation < 0 || isPredictedRotationAcceptable(now)) {

                mProposedRotation = mPredictedRotation;//关键数:4:新的建议方向等于预报方向。

            }

 

            // Write final statistics aboutwhere we are in the orientation detection process.

            if (LOG) {

                Slog.v(TAG, "Result: currentRotation=" +mOrientationListener.mCurrentRotation

                        + ",proposedRotation=" + mProposedRotation

                        + ",predictedRotation=" + mPredictedRotation

                        + ",timeDeltaMS=" + timeDeltaMS

                        + ",isAccelerating=" + isAccelerating

                        + ", isFlat="+ isFlat

                        + ",isSwinging=" + isSwinging

                        + ",timeUntilSettledMS=" + remainingMS(now,

                               mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS)

                        + ",timeUntilAccelerationDelayExpiredMS=" + remainingMS(now,

                               mAccelerationTimestampNanos +PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS)

                        + ",timeUntilFlatDelayExpiredMS=" + remainingMS(now,

                               mFlatTimestampNanos + PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS)

                        + ",timeUntilSwingDelayExpiredMS=" + remainingMS(now,

                               mSwingTimestampNanos + PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS));

            }

 

            // Tell the listener.

            if (mProposedRotation!= oldProposedRotation && mProposedRotation>= 0) {

                if (LOG) {

                    Slog.v(TAG, "Proposedrotation changed! proposedRotation=" + mProposedRotation

                            + ",oldProposedRotation=" + oldProposedRotation);

                }

                mOrientationListener.onProposedRotationChanged(mProposedRotation);

/*通知windoweservice去更新rotation*/

            }

        }

 

2.1     mOrientationListener.onProposedRotationChanged(mProposedRotation);

MyOrientationListener.onProposeRotationChange ---------- PhoneWindowManager.java

 

    class MyOrientationListener extendsWindowOrientationListener {

       

        @Override

        public void onProposedRotationChanged(introtation) {

            if (localLOGV) Log.v(TAG,"onProposedRotationChanged, rotation=" + rotation);

            updateRotation(false);

        }

    }

 

   关键结构:

1.        private static finalint[][]TILT_TOLERANCE = new int[][]{

参数含义:{旋转方向(0,90,180,270), 倾斜角}

            /* ROTATION_0   */ { -25, 70 },

            /* ROTATION_90  */ { -25, 65 },

            /* ROTATION_180 */ { -25, 60 },

            /* ROTATION_270 */ { -25, 65 }

        };

也就是tiltAngle在各个倾斜角的范围

 

2.这里有两个关键的方向

原来方向oldProposedRotation  等于 mProposedRotation

预报方向mPredictedRotation    等于 nearestRotation

 

 建议方向 mProposedRotation   如果条件满足等于 mPredictedRotation   

 

3.总的来说是否更新rotationlistenser 需要如下的条件(从Tell the listener往前推理)优化如下几个条件:

条件1):(mProposedRotation != oldProposedRotation && mProposedRotation >= 0)

条件2):新的预报方向 是否可以作为 建议方向的条件是:if (mPredictedRotation < 0 || isPredictedRotationAcceptable(now))

其中两个

isPredictedRotationAcceptable():是判断预报方向的在某时间内是否稳定;//可以缩短其时间 提高灵敏度

mPredictedRotation <0 : 说明tiltAngle和orientationAngle 都不在合理的范围内

条件3):所以tiltAngle和orientationAngle 不要进入 无效数据范围。可以调整TILT_TOLERANCEADJACENT_ORIENTATION_ANGLE_GAP 齿槽角(目前是45度)

isOrientationAngleAcceptable()//该函数会判断相邻方向之间的齿槽角差距

Case 1

// For example, if currentRotation is ROTATION_0(则rotation=0) and proposed is ROTATION_90(则rotation=1),

// then we want tocheck orientationAngle > 45 + GAP / 2.也就是最低的方向角下限

if (currentRotation>= 0) {

                // If the specified rotation isthe same or is counter-clockwise adjacent

                // to the current rotation,then we set a lower bound on the orientation angle.

                // For example, ifcurrentRotation is ROTATION_0 and proposed is ROTATION_90,

                // then we want to checkorientationAngle > 45 + GAP / 2.

                if (rotation == currentRotation

                        || rotation ==(currentRotation + 1) % 4) {

                    int lowerBound = rotation * 90 - 45+ADJACENT_ORIENTATION_ANGLE_GAP / 2; //lowerBound :最低下限

                    if (rotation == 0) {

                        if (orientationAngle>= 315 && orientationAngle < lowerBound + 360) {

                            return false;

                        }

                    } else {

                        if (orientationAngle< lowerBound) {

                            return false;

                        }

                    }

                }

所以说ADJACENT_ORIENTATION_ANGLE_GAP 越大,lowerBound 就越大,orientationAngle 就会越容易满足条件,

Case 2

//If the specified rotation is the same or is clockwise adjacent,

                // then we set an upper boundon the orientation angle.

                // For example, ifcurrentRotation is ROTATION_0 and rotation is ROTATION_270(则rotation=3) ,

                // then we want to checkorientationAngle < 315 - GAP / 2.

                if (rotation == currentRotation

                        || rotation ==(currentRotation + 3) % 4) {

                    int upperBound = rotation * 90 + 45- ADJACENT_ORIENTATION_ANGLE_GAP/ 2;

                    if (rotation == 0) {

                        if (orientationAngle<= 45 && orientationAngle > upperBound) {

                            return false;

                        }

                    } else {

                        if (orientationAngle> upperBound) {

                            return false;

                        }

                    }

                }

所以说ADJACENT_ORIENTATION_ANGLE_GAP 越小,upperBound 就越大,orientationAngle就会越容易满足条件,

 

条件4):nearestRotation 要发生变化

条件5):以调整转屏角度及转屏加速度delay方面的设置来达到些许优化转屏速度的目的

在函数:private boolean isPredictedRotationAcceptable(long now){}里面的时间

 

 

FAQ

1.客户有如下需求:

需校正重力感应角度,將機器放於桌面,用手托住機器一側,慢慢向上抬起,當機器後殼與桌面夾角角度達到45度時,畫面應能出現旋轉(四個方向都必須是到達45度角後才能旋轉)

--------

改变屏幕旋转的角度,可以修改frameworks/base/core/java/android/view/WindowOrientationListener.java中的MAX_TILT或者TILT_TOLERANCE

但是这样修改之后的影响不确定。

sensor:gsensor的流程以及优化分析

标签:gesnor   优化   旋转速度   

原文地址:http://blog.csdn.net/honour2sword/article/details/45315273

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!