【问题标题】:How can i get device tilt in xamarin forms?如何以 xamarin 形式获得设备倾斜?
【发布时间】:2017-08-29 19:23:43
【问题描述】:

我想得到设备的倾斜度,所以我可以用它来测量某个表面的倾斜度,将设备放在表面上。

现在我从这里https://github.com/rdelrosario/xamarin-plugins使用 xamarin 表单的 Device Motion 插件

以及下面的代码:

CrossDeviceMotion.Current.Start(MotionSensorType.Accelerometer);

    CrossDeviceMotion.Current.SensorValueChanged += (s, a) =>
    {

        switch (a.SensorType)
        {
            case MotionSensorType.Accelerometer:
                {
                    Debug.WriteLine("A: {0},{1},{2}", ((MotionVector)a.Value).X, ((MotionVector)a.Value).Y,
                     ((MotionVector)a.Value).Z);
                    Exposicao.Inclinacao = ((MotionVector)a.Value).Z;
                    break;
                }
            case MotionSensorType.Compass:
                {
                    // Debug.WriteLine("H: {0}", a.Value);
                    Exposicao.Bussola = (double)a.Value.Value;
                    break;
                }
        }
    };

指南针部分没问题,加速度计部分工作但有一些问题。

如果我没记错的话,我会得到 Z 轴的倾斜,所以 z.Value.Value。

这个值对于android和ios是不同的,让我们关注android。

z 值从设备平放时为 10 到设备竖立时为 0,仅聚焦在一个象限。

为了实现我所解释的,我做错了什么?

如何将这些值转换为 0 到 90 之间的角度?它似乎不是线性的,所以 5 似乎不是 45 度。

谢谢

【问题讨论】:

    标签: xamarin xamarin.forms devicemotion


    【解决方案1】:

    我可能会针对您正在寻找的功能推出自己的平台实现。 DeviceMotion 库对于您的目的来说看起来有点简单,从下面的答案中可以看出。我很确定您可以将其用作一个很好的起点,但需要对其进行一些扩展。

    安卓

    在 Android 上,您应该使用Rotation Vector Sensor,它使用卡尔曼滤波器(带有加速度计、磁力计和陀螺仪)来获得设备旋转的准确测量值:

    旋转矢量将设备的方向表示为角度和轴的组合,其中设备围绕轴(x、y 或 z)旋转了角度 θ。

    Image from the official Android documentation

    iOS:

    对于 iOS,您必须自己做更多的工作。关键是利用 CMAttitude,它描述了设备相对于初始姿态的姿态。我在这里找到了一个我从未知来源(不能归功于原作者)保存到我的收藏中的 sn-p:

    public void CalculateLeanAngle ()
    {           
        motionManager = new CMMotionManager ();
        motionManager.DeviceMotionUpdateInterval = 0.02; 
    
        if (motionManager.DeviceMotionAvailable) {
            motionManager.StartDeviceMotionUpdates(CMAttitudeReferenceFrame.XArbitraryZVertical, NSOperationQueue.CurrentQueue, (data, error) => { 
                CMQuaternion quat = motionManager.DeviceMotion.Attitude.Quaternion;
                double x = quat.x;
                double y = quat.y;
                double w = quat.w;
                double z = quat.z;
                double degrees = 0.0;
    
                //Roll
                double roll = Math.Atan2 (2 * y * w - 2 * x * z, 1 - 2 * y * y - 2 * z * z);                        
                degrees = Math.Round (-applyKalmanFiltering (roll) * 180.0 / Constants.M_PI);
        });
    }
    
    public double applyKalmanFiltering (double yaw)
    {
        if (motionLastYaw == 0)
            motionLastYaw = yaw;
    
        float q = 0.1f;   // process noise
        float r = 0.1f;   // sensor noise
        float p = 0.1f;   // estimated error
        float k = 0.5f;   // kalman filter gain
    
        double x = motionLastYaw;
        p = p + q;
        k = p / (p + r);
        x = x + k * (yaw - x);
        p = (1 - k) * p;
        motionLastYaw = x;
    
        return motionLastYaw;
    }
    

    Image from the official Xamarin documentation

    当我有更多时间时,我会尝试寻找原始来源,但我很确定这对于您的目的来说是开箱即用的。

    【讨论】:

    • 谢谢hankide,看起来很精确,但精度不是必需的,这就是我开始使用插件的原因,但是如果我有时间改进我会尝试一下,看看有没有人否则帮我将插件编号转换为度数
    • @gilberto 好的,有道理。希望有人有更简单的解决方案。
    • 不幸的是,我被困在那里,没有太多时间解决,有什么建议吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    相关资源
    最近更新 更多