Пытаясь управлять объектом с помощью гироскопа и акселерометра, почему он не работает?

Я пытаюсь управлять объектом, поворачивая мой телефон Android, так что если я наклоню камеру, объект наклонится. Это видео показывает, что я хочу, но я хочу контролировать это с помощью своего телефона.

С того же сайта, что и видео, я нашел реализацию aC#, подумал, что это будет прогулка по парку, чтобы перенести это в единство.

Код, который я использую, выглядит следующим образом:

using UnityEngine;
using System.Collections;
using System;

namespace AHRS
{
    public class MadgwickAHRS
    {
        public float SamplePeriod { get; set; }
        public float Beta { get; set; }
        public float[] QuaternionArray { get; set; }
        public Quaternion quaternion { get; set; }
        public MadgwickAHRS(float samplePeriod)
            : this(samplePeriod, 1f)
        {
        }
        public MadgwickAHRS(float samplePeriod, float beta)
        {
            SamplePeriod = samplePeriod;
            Beta = beta;
            QuaternionArray = new float[] { 1f, 0f, 0f, 0f };
        }

        public void Update(float gx, float gy, float gz, float ax, float ay, float az)
        {
            float q1 = QuaternionArray[0], q2 = QuaternionArray[1], q3 = QuaternionArray[2], q4 = QuaternionArray[3];   // short name local variable for readability
            float norm;
            float s1, s2, s3, s4;
            float qDot1, qDot2, qDot3, qDot4;

            // Auxiliary variables to avoid repeated arithmetic
            float _2q1 = 2f * q1;
            float _2q2 = 2f * q2;
            float _2q3 = 2f * q3;
            float _2q4 = 2f * q4;
            float _4q1 = 4f * q1;
            float _4q2 = 4f * q2;
            float _4q3 = 4f * q3;
            float _8q2 = 8f * q2;
            float _8q3 = 8f * q3;
            float q1q1 = q1 * q1;
            float q2q2 = q2 * q2;
            float q3q3 = q3 * q3;
            float q4q4 = q4 * q4;

            // Normalise accelerometer measurement
            norm = (float)Math.Sqrt(ax * ax + ay * ay + az * az);
            if (norm == 0f) return; // handle NaN
            norm = 1 / norm;        // use reciprocal for division
            ax *= norm;
            ay *= norm;
            az *= norm;

            // Gradient decent algorithm corrective step
            s1 = _4q1 * q3q3 + _2q3 * ax + _4q1 * q2q2 - _2q2 * ay;
            s2 = _4q2 * q4q4 - _2q4 * ax + 4f * q1q1 * q2 - _2q1 * ay - _4q2 + _8q2 * q2q2 + _8q2 * q3q3 + _4q2 * az;
            s3 = 4f * q1q1 * q3 + _2q1 * ax + _4q3 * q4q4 - _2q4 * ay - _4q3 + _8q3 * q2q2 + _8q3 * q3q3 + _4q3 * az;
            s4 = 4f * q2q2 * q4 - _2q2 * ax + 4f * q3q3 * q4 - _2q3 * ay;
            norm = 1f / (float)Math.Sqrt(s1 * s1 + s2 * s2 + s3 * s3 + s4 * s4);    // normalise step magnitude
            s1 *= norm;
            s2 *= norm;
            s3 *= norm;
            s4 *= norm;

            // Compute rate of change of quaternion
            qDot1 = 0.5f * (-q2 * gx - q3 * gy - q4 * gz) - Beta * s1;
            qDot2 = 0.5f * (q1 * gx + q3 * gz - q4 * gy) - Beta * s2;
            qDot3 = 0.5f * (q1 * gy - q2 * gz + q4 * gx) - Beta * s3;
            qDot4 = 0.5f * (q1 * gz + q2 * gy - q3 * gx) - Beta * s4;

            // Integrate to yield quaternion
            q1 += qDot1 * SamplePeriod;
            q2 += qDot2 * SamplePeriod;
            q3 += qDot3 * SamplePeriod;
            q4 += qDot4 * SamplePeriod;
            norm = 1f / (float)Math.Sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4);    // normalise quaternion
            QuaternionArray[0] = q1 * norm;
            QuaternionArray[1] = q2 * norm;
            QuaternionArray[2] = q3 * norm;
            QuaternionArray[3] = q4 * norm;

            quaternion = new Quaternion (
                QuaternionArray[0],
                QuaternionArray[1],
                QuaternionArray[2],
                QuaternionArray[3]);
        }
    }
}

public class CompassHeading : MonoBehaviour {

    AHRS.MadgwickAHRS ahrs = new AHRS.MadgwickAHRS(1f/200f);

    void Update(){
        ahrs.Update(
            Input.gyro.rotationRateUnbiased.x, 
            Input.gyro.rotationRateUnbiased.y, 
            Input.gyro.rotationRateUnbiased.z, 
            Input.acceleration.x,
            Input.acceleration.y,
            Input.acceleration.z);
        transform.rotation = ahrs.quaternion;
    }
}

Я прикрепляю этот скрипт к кубу, но когда я поворачиваю свой телефон, куб вращается вокруг неправильной оси. Например: если я вращаюсь вокруг оси x, куб поворачивается вокруг оси z. Может кто-нибудь помочь мне понять этот код и заставить его работать? Я действительно нуб, когда дело доходит до вращений и кватернионов...

1 ответ

Вы вызываете функцию для выполнения вращений здесь:

void Update(){
    ahrs.Update(
        Input.gyro.rotationRateUnbiased.x, 
        Input.gyro.rotationRateUnbiased.y, 
        Input.gyro.rotationRateUnbiased.z, 
        Input.acceleration.x,
        Input.acceleration.y,
        Input.acceleration.z);
    transform.rotation = ahrs.quaternion;
}

Вы можете просто поменять направления, которые вы хотите здесь. например, если ваши оси x и z неверны, вы должны сделать это следующим образом:

void Update(){
    ahrs.Update(
        Input.gyro.rotationRateUnbiased.z, 
        Input.gyro.rotationRateUnbiased.y, 
        Input.gyro.rotationRateUnbiased.x, 
        Input.acceleration.z,
        Input.acceleration.y,
        Input.acceleration.x);
    transform.rotation = ahrs.quaternion;
}
Другие вопросы по тегам