2013-07-29 1 views
4

방향을 기준으로 개체를 가리 키기위한 증강 현실보기를 만들고 싶습니다. 그러나 카메라로 위쪽을 향하고있을 때 CoreLocation 헤딩이 제대로 작동하지 않습니다 (1 층에있을 때 20 층짜리 건물 꼭대기라고 말하면됩니다).CoreLocation 머리글 기반 카메라 뒷면 (증강 현실)

반대 방향 (아마도 휴대 전화의 위쪽을 가리키는 방향)을 제공합니다.

내가 같은 카메라가 가리키는 방향을 위해 일을 얻을 수있는 몇 가지 방법을 시도 :

1, 180 정도 때 장치 방향은> 45도 (충분히 정확하지, 갑자기입니다 방향이 10 ~ 20도 흐려짐)

2, 아래 튜토리얼의 수식을 사용하여 CMMotionManager를 사용하여 계산하려고했습니다. http://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial.

3, ios deviceMotion.magneticField 및 deviceMotion.gravity를 사용하여 Android에서 로직을 시뮬 레이팅하려고 시도했습니다.

4, 사용 회전 행렬 (스택 오버 플로우에서 다른 포스트, 정확한되지 않음)

double heading = M_PI + atan2(self.altitudeData.rotationMatrix.m22, self.altitudeData.rotationMatrix.m12); 
    heading = heading*180/M_PI; 

내가 생각이 부족하고 다른 내가 바로 그걸 얻기 위해 시도 할 수 있습니다. 거기에 몇 가지 애플 리케이션이 있다는 것을 알고 (일부 애플은 태양과 스타를 볼 수 있습니다) 제대로하고있다.

답변

12

많은 연구와 테스트를 거친 후. GLKit을 사용하여 계산을 마쳤습니다. 문제가 많아졌습니다. 이 질문에 이르면 누구 에게라도 남겨주세요.

먼저 CMAttitudeReferenceFrameXTrueNorthZVertical을 사용하여 CMMotionManager 장치 모션 업데이트를 시작했습니다. 내가 CoreMotion 회전을 사용하여 OpenGL을 세계를 그리고 3D 세계에 화면에서 점을 받고 그것을 혼합 웹에서 발견 된 일부 코드에서

self.hasMotion = NO; 
CMMotionManager *cmmotionManager = [[CMMotionManager alloc] init]; 
[cmmotionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical 
                toQueue:[[NSOperationQueue alloc] init] 
               withHandler:^ (CMDeviceMotion *motion, NSError *error) { 
                self.hasMotion = YES; 


               }]; 
self.motionManager = cmmotionManager; 

:

float aspect = fabsf(self.view.bounds.size.width/self.view.bounds.size.height); 
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0f), aspect, 0.1f, 100.0f); 

CMRotationMatrix r = self.motionManager.deviceMotion.attitude.rotationMatrix; 
GLKMatrix4 camFromIMU = GLKMatrix4Make(r.m11, r.m12, r.m13, 0, 
             r.m21, r.m22, r.m23, 0, 
             r.m31, r.m32, r.m33, 0, 
             0,  0,  0,  1); 

GLKMatrix4 viewFromCam = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, 0); 
GLKMatrix4 imuFromModel = GLKMatrix4Identity; 
GLKMatrix4 viewModel = GLKMatrix4Multiply(imuFromModel, GLKMatrix4Multiply(camFromIMU, viewFromCam)); 
bool isInvertible; 
GLKMatrix4 modelView = GLKMatrix4Invert(viewModel, &isInvertible); 

int viewport[4]; 
viewport[0] = 0.0f; 
viewport[1] = 0.0f; 
viewport[2] = self.view.frame.size.width; 
viewport[3] = self.view.frame.size.height; 

bool success; 
//assume center of the view 
GLKVector3 vector3 = GLKVector3Make(self.view.frame.size.width/2, self.view.frame.size.height/2, 1.0);  
GLKVector3 calculatedPoint = GLKMathUnproject(vector3, modelView, projectionMatrix, viewport, &success); 
if(success) 
{ 
    //CMAttitudeReferenceFrameXTrueNorthZVertical always point x to true north 
    //with that, -y become east in 3D world 
    float angleInRadian = atan2f(-calculatedPoint.y, calculatedPoint.x); 
    return angleInRadian; 
} 
+0

감사합니다. user2629068, 모든 방법이 예상대로 작동합니다. – kokemomuke

+0

좋습니다! 이 문제를 해결하려고하는 그물에 수많은 솔루션이 있습니다. 그러나 이것은 잘 작동하는 유일한 것입니다. –

+0

내 카메라의 미세한 움직임을 아주 잘 지원하는이 코드를 보내 주셔서 감사합니다! 그러나 나는 대략 10 도의 표제의 정확도를 가지고있다. 이 정확성을 더 낮은 값으로 줄이는 방법이 있습니까? (따라서 제목의 정확성이 향상됩니까?) –

1

이 다른 사람의 시간을 절약하기 위해, 스위프트의 Chee의 답변은 다음과 같습니다.

import GLKit  

func headingCorrectedForTilt() -> Float?{ 
     guard let motion = self.motionManager.deviceMotion else{ 
      return nil 
     } 

     let aspect = fabsf(Float(self.view.bounds.width/self.view.bounds.height)) 
     let projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0), aspect, 0.1, 100) 


     let r = motion.attitude.rotationMatrix 
     let camFromIMU = GLKMatrix4Make(Float(r.m11), Float(r.m12), Float(r.m13), 0, 
          Float(r.m21), Float(r.m22), Float(r.m23), 0, 
          Float(r.m31), Float(r.m32), Float(r.m33), 0, 
          0,  0,  0,  1) 

     let viewFromCam = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, 0); 
     let imuFromModel = GLKMatrix4Identity 
     let viewModel = GLKMatrix4Multiply(imuFromModel, GLKMatrix4Multiply(camFromIMU, viewFromCam)) 
     var isInvertible : Bool = false 
     let modelView = GLKMatrix4Invert(viewModel, &isInvertible); 
     var viewport = [Int32](count:4,repeatedValue: 0) 

     viewport[0] = 0; 
     viewport[1] = 0; 
     viewport[2] = Int32(self.view.frame.size.width); 
     viewport[3] = Int32(self.view.frame.size.height); 

     var success: Bool = false 
     let vector3 = GLKVector3Make(Float(self.view.frame.size.width)/2, Float(self.view.frame.size.height)/2, 1.0) 
     let calculatedPoint = GLKMathUnproject(vector3, modelView, projectionMatrix, &viewport, &success) 

     return success ? atan2f(-calculatedPoint.y, calculatedPoint.x) : nil 
    }