Как трябва да изчисля 3 оси на световните координати от движението на устройството?

Имам проблем с конвертирането на данните за движението на устройството в световни координати.

Разглеждах ротационни/проекционни матрици и кватерниони, но CMAttitude (roll, pitch, yaw) е мястото, където постигнах най-голям успех с помощта на gravity.y и gravity.z за намиране на ориентацията на устройството около същата ос като pitch.

Крайният резултат, който търся, е усещане за разширена/виртуална реалност, тъй като потребителят търси 2D игрови обекти около централна точка.


person Lohardt    schedule 27.03.2012    source източник


Отговори (2)


Не бих използвал ъгли на Ойлер (наклон, наклон, отклонение). Това доста прецаква стабилността на приложението ви, вижте тук защо: Странно поведение със сензор за ориентация на Android.

Бих използвал ротационни матрици. Те ви казват как да преминете от координатите на устройството към световните координати и обратното. Може да намерите тези полезни:

person Ali    schedule 27.03.2012
comment
Познавате ли някакъв публичен изходен код, използващ това? Няма да имам нищо против таксите. - person Nils Munch; 27.03.2012
comment
Свързаното теоретично въведение е наистина добро и лесно за разбиране. Не мисля, че изходният код би бил по-лесен за разбиране от това. - person Ali; 27.03.2012
comment
Разглеждах developer.apple.com/library/ios/#samplecode/pARk/Listings/, но замяната на функциите, които преобразуват GPS координатите в проекционната матрица, беше трудна. - person Lohardt; 28.03.2012
comment
GPS координатите нямат нищо общо с отношението на устройството. Не можете да конвертирате GPS координати в ротационни матрици. - person Ali; 28.03.2012
comment
Знам, че приложението Park преобразува GPS координатите в ECEF, след това в ENU и след това в кватернион и ги подава към проекционна матрица. Опитах се да създам кватернион с моите начални позиции на игрови обекти и да го захраня с матрицата, но досега нямам успех. - person Lohardt; 28.03.2012
comment
@Lohardt Радвам се да видя, че отговорът ми е полезен. Късмет! - person Ali; 25.06.2012

В момента работя върху базирано на накланяне приложение и реших да споделя какво открих в крайна сметка. Този код преобразува от кватернион в ъгли на Ойлер (изглежда като XYX или ZYZ) и ъгли на Тейт-Браян (изглежда като XYZ или ZYX), въпреки че аз самият съм използвал само ъглите на Тейт-Браян. След отгатване и проверка през ъглите на Tait-Bryan открих, че ZXY работи идеално за моите цели.

Ето връзката: http://bediyap.com/programming/convert-quaternion-to-euler-rotations/

А ето и кода:

///////////////////////////////
// Quaternion to Euler
///////////////////////////////
enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx};

void twoaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
  res[0] = atan2( r11, r12 );
  res[1] = acos ( r21 );
  res[2] = atan2( r31, r32 );
}

void threeaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
  res[0] = atan2( r31, r32 );
  res[1] = asin ( r21 );
  res[2] = atan2( r11, r12 );
}

void quaternion2Euler(const Quaternion& q, double res[], RotSeq rotSeq)
{
    switch(rotSeq){
    case zyx:
      threeaxisrot( 2*(q.x*q.y + q.w*q.z),
                     q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                    -2*(q.x*q.z - q.w*q.y),
                     2*(q.y*q.z + q.w*q.x),
                     q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                     res);
      break;

    case zyz:
      twoaxisrot( 2*(q.y*q.z - q.w*q.x),
                   2*(q.x*q.z + q.w*q.y),
                   q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                   2*(q.y*q.z + q.w*q.x),
                  -2*(q.x*q.z - q.w*q.y),
                  res);
      break;

    case zxy:
      threeaxisrot( -2*(q.x*q.y - q.w*q.z),
                      q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                      2*(q.y*q.z + q.w*q.x),
                     -2*(q.x*q.z - q.w*q.y),
                      q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                      res);
      break;

    case zxz:
      twoaxisrot( 2*(q.x*q.z + q.w*q.y),
                  -2*(q.y*q.z - q.w*q.x),
                   q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                   2*(q.x*q.z - q.w*q.y),
                   2*(q.y*q.z + q.w*q.x),
                   res);
      break;

    case yxz:
      threeaxisrot( 2*(q.x*q.z + q.w*q.y),
                     q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                    -2*(q.y*q.z - q.w*q.x),
                     2*(q.x*q.y + q.w*q.z),
                     q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                     res);
      break;

    case yxy:
      twoaxisrot( 2*(q.x*q.y - q.w*q.z),
                   2*(q.y*q.z + q.w*q.x),
                   q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                   2*(q.x*q.y + q.w*q.z),
                  -2*(q.y*q.z - q.w*q.x),
                  res);
      break;

    case yzx:
      threeaxisrot( -2*(q.x*q.z - q.w*q.y),
                      q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                      2*(q.x*q.y + q.w*q.z),
                     -2*(q.y*q.z - q.w*q.x),
                      q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                      res);
      break;

    case yzy:
      twoaxisrot( 2*(q.y*q.z + q.w*q.x),
                  -2*(q.x*q.y - q.w*q.z),
                   q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                   2*(q.y*q.z - q.w*q.x),
                   2*(q.x*q.y + q.w*q.z),
                   res);
      break;

    case xyz:
      threeaxisrot( -2*(q.y*q.z - q.w*q.x),
                    q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                    2*(q.x*q.z + q.w*q.y),
                   -2*(q.x*q.y - q.w*q.z),
                    q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                    res);
      break;

    case xyx:
      twoaxisrot( 2*(q.x*q.y + q.w*q.z),
                  -2*(q.x*q.z - q.w*q.y),
                   q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                   2*(q.x*q.y - q.w*q.z),
                   2*(q.x*q.z + q.w*q.y),
                   res);
      break;

    case xzy:
      threeaxisrot( 2*(q.y*q.z + q.w*q.x),
                     q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                    -2*(q.x*q.y - q.w*q.z),
                     2*(q.x*q.z + q.w*q.y),
                     q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                     res);
      break;

    case xzx:
      twoaxisrot( 2*(q.x*q.z - q.w*q.y),
                   2*(q.x*q.y + q.w*q.z),
                   q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                   2*(q.x*q.z + q.w*q.y),
                  -2*(q.x*q.y - q.w*q.z),
                  res);
      break;
    default:
      std::cout << "Unknown rotation sequence" << std::endl;
      break;
   }
}
person frodo2975    schedule 16.12.2014