¿Cómo calcular la orientación de un sensor IMU?

Con un sensor BLE CPro , estoy tratando de "construir" un control remoto para un juego de teléfono inteligente. ¿Cómo puedo reconocer la orientación (graduaciones preferidas) del sensor si está a la izquierda o a la derecha sin que me afecte su gravedad? es decir, en un entorno agitado/en movimiento?

ingrese la descripción de la imagen aquí

Mi problema es que si calculo la orientación usando el acelerómetro, cada vez que se sacude el sensor, la gravedad cambia drásticamente, lo que dificulta saber la orientación actual.

Este sensor CPro ofrece un ejemplo de cómo calcular sus cuaterniones. Como resultado, muestra un gráfico de cubo usando OpenGL ES que sigue la orientación/rotación del sensor. Desafortunadamente, no entiendo muy bien cómo puedo obtener de los cuaterniones la orientación en grados...

//src https://github.com/mbientlab-projects/iOSSensorFusion/tree/master
- (void)performKalmanUpdate
{
    [self.estimator readAccel:self.accelData
                        rates:self.gyroData
                        field:self.magnetometerData];

    if (self.estimator.compassCalibrated && self.estimator.gyroCalibrated)
    {
        auto q = self.estimator.eskf->getState();
        auto g = self.estimator.eskf->getAPred();

        auto a = self.accelData;
        auto w = self.gyroData;

        auto mp = self.estimator.eskf->getMPred();
        auto m = self.estimator.eskf->getMMeas();

        _s->qvals[0] = q.a();
        _s->qvals[1] = q.b();
        _s->qvals[2] = q.c();
        _s->qvals[3] = q.d();

        //  calculate un-filtered angles
        float ay = -a.y;
        if (ay < -1.0f) {
            ay = -1.0f;
        } else if (ay > 1.0f) {
            ay = 1.0f;
        }
        _s->ang[1] = std::atan2(-a.x, -a.z);
        _s->ang[0] = std::asin(-ay);
        _s->ang[2] = std::atan2(m(1), m(0)); //  hack: using the filtered cos/theta to tilt-compensate here

        //  send transform to render view
        auto R = q.to_matrix();

        GLKMatrix4 trans = GLKMatrix4Identity;
        auto M = GLKMatrix4MakeAndTranspose(R(0,0), R(0,1), R(0,2), 0.0f,
                                            R(1,0), R(1,1), R(1,2), 0.0f,
                                            R(2,0), R(2,1), R(2,2), 0.0f,
                                            0.0f, 0.0f, 0.0f, 1.0f);

        trans = GLKMatrix4Multiply(trans, M);
        self.renderVC.cubeOrientation = trans;
    }
}

Respuestas (1)

Como ha descubierto, un acelerómetro de tres ejes solo le indicará la orientación cuando algo sea básicamente estable. O estable en promedio si puede tolerar una respuesta lenta debido al filtrado requerido para filtrar el componente vibratorio de la señal. En su lugar, para encontrar la orientación del sensor en tales condiciones, puede usar un giroscopio de 3 ejes, que no es muy sensible a la vibración, y tomar la integral de la salida de velocidad de giro que da para encontrar la orientación y corregir la desviación del giroscopio. usando algún tipo de información adicional, típicamente de acelerómetros y magnetómetros, que te dan los vectores de gravedad y el campo magnético de la tierra. Los esquemas de filtro de Kalman son comunes aquí.

Hoy en día, puede comprar sensores que hacen esto por usted y que generan los ángulos de Euler o una representación de cuaterniones de la orientación del sensor en relación con ser plano. Busque sensores de unidad de medida inercial (IMU) que anuncien que tienen Sensor Fusion .

Su ejemplo de código anterior está haciendo esto, utilizando los otros sensores presentes en su sensor CPro con un filtro de Kalman para obtener una mejor estimación de la orientación del sensor como un cuaternión, que luego se convierte en una matriz de transformación mediante el método to_matrix() . Puede encontrar más información sobre cómo convertir un cuaternión en ángulos de Euler, que es lo que creo que desea, en este artículo: Conversión entre cuaterniones y ángulos de Euler