Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoreMotion - get left-right, bottom-up movement on iPhone in landscape

I am making an App which able to make panorama video in landscape. In landscape, it supports two directions: left to right and bottom to top.

So I want to move an arrow from left to right when user move the phone from left to right or rotate to right. Also want to move the arrow bottom to top when move the device vertically upwards. In native iPhone camera app with panorama option, there we can see the correct simulation,

My questions are 1) how do I know user is moving the phone from left to right or right to left. Because like iPhone panorama, I want to stop recording when user move back.

Also 2) how do I know user is moving the phone vertically upwards


Added : Nov 10, 2017: I did see an app named Spincle in AppStore. It is moving the arrow when rotate the device from left to right to take 360 image. I just managed to achieve this using pitch and roll (see the below code). But this will not work if we stand device to floor or roof a bit.

import UIKit
import CoreMotion
class ViewController: UIViewController {
    private let motionManager = CMMotionManager()
    let arrowView = UIView()
    func startMotion() {
        var initialAttitude: CMAttitude?
        motionManager.deviceMotionUpdateInterval = 1
        let queue = OperationQueue.current!
        let statusBarOrientation = UIApplication.shared.statusBarOrientation
        motionManager.startDeviceMotionUpdates(using: CMAttitudeReferenceFrame.xArbitraryZVertical, to: queue) { (motiondata, err) in
            guard let data = motiondata else { return }
            if initialAttitude == nil {
                initialAttitude = data.attitude
            } else {
                let attitude = data.attitude
                // translate the attitude
                attitude.multiply(byInverseOf: initialAttitude!)
                // calculate pitch and roll of the change from our initial attitude
                let pitch = self.radiansToDegrees(attitude.pitch)
                let roll = self.radiansToDegrees(attitude.roll)
                print("\nroll = \(roll), pitch = \(pitch), yaw = \(self.radiansToDegrees(attitude.yaw))")
                print("x = \(data.userAcceleration.x), y = \(data.userAcceleration.y), z = \(data.userAcceleration.z)")
                DispatchQueue.main.async {
                    var rect = self.arrowView.frame
                    var addXPixel = self.view.frame.size.width/45
                    var addYPixel = self.view.frame.size.height/45
                    if statusBarOrientation == .landscapeRight {
                        addXPixel *= -1
                    } else {
                        addYPixel *= -1
                    }
                    rect.origin.x = (CGFloat(pitch) * addXPixel)
                    rect.origin.y = (self.view.frame.size.height/2 - 20) + (CGFloat(roll) * addYPixel)
                    self.arrowView.frame = rect
                }
            }
        }
    }
    func stopMotion() {
        motionManager.stopDeviceMotionUpdates()
    }
    func radiansToDegrees(_ radian: Double) -> Float {
        return Float(radian * 180.0/Double.pi)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(arrowView)
        arrowView.backgroundColor = UIColor.red
    }
    @IBAction func tappedButton() {
        arrowView.frame = CGRect(x: 0, y: self.view.frame.size.height/2 - 20, width: 40, height: 40)
        startMotion()
    }
}

The issue is it will go left to right a bit and the arrow moving upwards or downwards

like image 880
jpulikkottil Avatar asked Nov 04 '17 09:11

jpulikkottil


1 Answers

You can use CLLocationManager to check the heading of your phone, and write your algorithm to determine the left-right / bottom-top movement by calculating CLHeading's degrees.

- (void)locationManager:(CLLocationManager*)manager 
        didUpdateHeading:(CLHeading*)newHeading

https://developer.apple.com/documentation/corelocation/clheading

like image 179
KTang Avatar answered Sep 19 '22 03:09

KTang