2011-03-03 3 views
2

현재 CoreMotion의 DeviceMotion을 사용하여 iPhone의 방향 (롤, 피치, 요)을 얻고 있습니다. 이제이 값을 지리적 북쪽 극점에 상대적으로 나타내려고합니다. 그래서 iPhone의 뒷면이 북극 (3D)을 향하게되면 롤, 피치 및 요 값을 포함하는 CMAttitude 참조 객체가 필요합니다. CLLocationManager는 Tesla에서 자기 머리글 (x, y, z) 만 반환합니다.iOS CoreMotion 북극을 기준으로 한 CMA 태도 ​​

롤, 피치 및 요로 값을 변환하는 방법에 대한 아이디어가 있습니까? 미리

감사

알렉산더

답변

-1

테슬라 값은 자기장 강도, 3 개 개의 축 각각에 느껴지는 얼마나 자기 "풀"의 척도이다. 이 정보를 가속도계 데이터와 결합하고 멋진 수학을 수행 할 때만 실제 표제 (장치가 자기 북쪽을 기준으로 "가리키는"방향)를 얻을 수 있습니까? 그런 다음 GPS에서 정보를 추가하고 더 많은 수학을 수행하여 진북 방향 (지형의 북극을 기준으로 함)을 얻습니다.

간단히 말해서, 당신은 아마 수학을 직접하고 싶지 않을 것입니다. 운좋게도 iOS는 CLHeading 객체에 magneticHeading과 trueHeading을 모두 제공하며 CLLocationManager 제목 속성에서 사용할 수 있습니다.

장치 기울임을 나타내는 피치 및 롤을 얻으려면 자력계 및 가속도계의 동일한 원시 데이터에 대해 계산을 수행해야합니다. 미안 피치 및 롤에 대한 iOS API에 대해 잘 모릅니다.

3

iOS 5는 지정된 방법을 제공합니다. 개발자 설명서에서 CMAttitudeReferenceFrameXTrueNorthZVertical을 찾으십시오.

1

의사 코드 : 백그라운드에서 카메라 미리보기를 시작

    1. 시작 장치 모션 업데이트
    2. )
    3. 캡처 현재의 중력 읽기 장치에서 CMAcceleration ... 일단 중력을 로컬 변수에 저장하면됩니다.
    4. 그러면 두 개의 벡터를 가져 와서 그 사이의 각도,이 경우 장치 중력 (0,0, -1)과 실제 중력 벡터를 얻어야합니다 ...
    5. 다음 세타를 thetaPrime ... CoreMotion 참조 방향과 일치하는 변환
    6. 애니메이션 할 타이머 설정 ....
    7. animation은 motionManager의 deviceMotion 속성의 rotationMatrix와 반대입니다.
    8. 다음은 장치의 현재 태도 (요, 피치, 오일러 모드 또는 장치 사원 수 회전 롤 ... 3 개 가지 방법이 기본적으로 똑같은 말을)

    을 반영하기 위해 올바른 순서로 변환 적용 코드는

    - (void) initMotionCapture 
    { 
        firstGravityReading = NO; 
        referenceAttitude = nil; 
    
        if (motionManager == nil) 
        { 
         self.motionManager = [CMMotionManager new]; 
        } 
        motionManager.deviceMotionUpdateInterval = 0.01; 
        self.gravityTimer = [NSTimer scheduledTimerWithTimeInterval:1/60.0 target:self selector:@selector(getFirstGravityReading) userInfo:nil repeats:YES]; 
    } 
    
    
    - (void) getFirstGravityReading 
    { 
        CMAcceleration currentGravity; 
    
        CMDeviceMotion *dm = motionManager.deviceMotion; 
        referenceAttitude = dm.attitude; 
        currentGravity = dm.gravity; 
    
        [motionManager startDeviceMotionUpdates]; 
    
        if (currentGravity.x !=0 && currentGravity.y !=0 && currentGravity.z !=0) 
        { 
         NSLog(@"Gravity = (%f,%f,%f)", currentGravity.x, currentGravity.y, currentGravity.z); 
    
         firstGravityReading = YES; 
         [gravityTimer invalidate]; 
         self.gravityTimer = nil; 
         [self setupCompass]; 
        } 
    } 
    
    - (void) setupCompass 
    { 
        //Draw your cube... I am using a quartz 3D perspective hack! 
        CATransform3D initialTransform = perspectiveTransformedLayer.sublayerTransform; 
        initialTransform.m34 = 1.0/-10000; 
    
    
        //HERE IS WHAT YOU GUYS NEED... the vector equations! 
        NSLog(@"Gravity = (%f,%f,%f)", currentGravity.x, currentGravity.y, currentGravity.z); 
    
        //we have current gravity vector and our device gravity vector of (0, 0, -1) 
        // get the dot product 
        float dotProduct = currentGravity.x*0 + currentGravity.y*0 + currentGravity.z*-1; 
        float innerMagnitudeProduct = currentGravity.x*currentGravity.x + currentGravity.y + currentGravity.y + currentGravity.z*currentGravity.z; 
        float magnitudeCurrentGravity = sqrt(innerMagnitudeProduct); 
        float magnitudeDeviceVector = 1; //since (0,0,-1) computes to: 0*0 + 0*0 + -1*-1 = 1 
    
        thetaOffset = acos(dotProduct/(magnitudeCurrentGravity*magnitudeDeviceVector)); 
        NSLog(@"theta(degrees) = %f", thetaOffset*180.0/M_PI); 
    
        //Now we have the device angle to the gravity vector (0,0,-1) 
        //We must transform these coordinates to match our 
        //device's attitude by transforming to theta prime 
        float theta_deg = thetaOffset*180.0/M_PI; 
        float thetaPrime_deg = -theta_deg + 90; // ThetaPrime = -Theta + 90 <==> y=mx+b 
    
        NSLog(@"thetaPrime(degrees) = %f", thetaOffset*180.0/M_PI); 
    
        deviceOffsetRotation = CATransform3DMakeRotation((thetaPrime_deg) * M_PI/180.0, 1, 0, 0); 
        initialTransform = CATransform3DConcat(deviceOffsetRotation, initialTransform); 
    
        perspectiveTransformedLayer.sublayerTransform = initialTransform; 
    
        self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:1/60.0 target:self selector:@selector(tick) userInfo:nil repeats:YES]; 
    
    } 
    
    - (void) tick 
    { 
        CMRotationMatrix rotation; 
    
        CMDeviceMotion *deviceMotion = motionManager.deviceMotion; 
        CMAttitude *attitude = deviceMotion.attitude; 
    
        if (referenceAttitude != nil) 
        { 
         [attitude multiplyByInverseOfAttitude:referenceAttitude]; 
        } 
        rotation = attitude.rotationMatrix; 
    
        CATransform3D rotationalTransform = perspectiveTransformedLayer.sublayerTransform; 
    
        //inverse (or called the transpose) of the attitude.rotationalMatrix 
        rotationalTransform.m11 = rotation.m11; 
        rotationalTransform.m12 = rotation.m21; 
        rotationalTransform.m13 = rotation.m31; 
    
        rotationalTransform.m21 = rotation.m12; 
        rotationalTransform.m22 = rotation.m22; 
        rotationalTransform.m23 = rotation.m32; 
    
        rotationalTransform.m31 = rotation.m13; 
        rotationalTransform.m32 = rotation.m23; 
        rotationalTransform.m33 = rotation.m33; 
    
        rotationalTransform = CATransform3DConcat(deviceOffsetRotation, rotationalTransform); 
        rotationalTransform = CATransform3DConcat(rotationalTransform, CATransform3DMakeScale(1.0, -1.0, 1.0)); 
    
    
        perspectiveTransformedLayer.sublayerTransform = rotationalTransform; 
    } 
    
    입니다.
  • 관련 문제