jpu*_*til 7 accelerometer ios core-motion swift
我正在制作一个能够在风景中制作全景视频的应用程序.在横向上,它支持两个方向:从左到右,从下到上.
因此,当用户从左向右移动手机或向右旋转时,我想从左向右移动箭头.当垂直向上移动设备时,也希望将箭头从底部移到顶部.在具有全景选项的原生iPhone相机应用程序中,我们可以看到正确的模拟,
我的问题是1)我怎么知道用户正在从左到右或从右到左移动手机.因为像iPhone全景,我想在用户搬回时停止录制.
另外2)我怎么知道用户正在垂直向上移动手机
补充:2017年11月10日:我确实在AppStore中看到了一个名为Spincle的应用程序.从左向右旋转设备时,它会移动箭头以拍摄360度图像.我只是设法使用俯仰和滚动来实现这一点(参见下面的代码).但是,如果我们将设备放在地板或屋顶上,这将无法工作.
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()
}
}
Run Code Online (Sandbox Code Playgroud)
问题是它会向左右移动,箭头向上或向下移动
我在横向模式下使用该应用程序,所以这个答案是基于此的。也许需要一点点改变才能使其适用于肖像。
我们将使用以下代码获取设备的 X、Y 和 Z 旋转。这里我们存储了初始值来获取与起始位置的角度差。
var initialAttitude: CMAttitude?
var initialRoll: Float?
var initialRotation: Float?//+20171219
func startMotion() {
initialAttitude = nil
initialRoll = nil
initialRotation = nil
//leaving first two values to confirm we are starting from corect
var counter = 0
motionManager.deviceMotionUpdateInterval = 0.001//+20180206
let queue = OperationQueue.current!
//
motionManager.startDeviceMotionUpdates(using: CMAttitudeReferenceFrame.xArbitraryZVertical, to: queue) { [weak self] (motiondata, _) in
guard let strongSelf = self, let data = motiondata else { return }
if strongSelf.initialAttitude == nil || counter < 2 {
strongSelf.initialAttitude = data.attitude
//initialize roll for horixontal rail
let myRoll = data.attitude.roll.toDegree()
strongSelf.initialRoll = abs(myRoll)
//initialize yaw for vertical rail
let rotation = (atan2(data.gravity.x, data.gravity.y) - Double.pi).toDegree()
strongSelf.initialRotation = abs(rotation)
//printDebug("myRoll = \(myRoll), myYaw = \(myYaw)")
globalMainQueue.async {
strongSelf.delegate?.updatedMotion(roll: 0, pitch: 0, yaw: 0)
}
counter += 1
} else {
let attitude = data.attitude
let myRoll = attitude.roll.toDegree()
let rotation = (atan2(data.gravity.x, data.gravity.y) - Double.pi).toDegree()
// translate the attitude
attitude.multiply(byInverseOf: strongSelf.initialAttitude!)
// calculate pitch and roll of the change from our initial attitude
let quat = attitude.quaternion
let pitch = (atan2(2*(quat.x*quat.w + quat.y*quat.z), 1 - 2*quat.x*quat.x - 2*quat.z*quat.z)).toDegree()
//printDebug("x = \(data.userAcceleration.x), y = \(data.userAcceleration.y), z = \(data.userAcceleration.z)")
let absRoll = abs(myRoll)
var newAbsRoll = abs(absRoll - strongSelf.initialRoll!)
if absRoll < strongSelf.initialRoll! {
newAbsRoll *= -1
}
printDebug("rotation = \(rotation)")
let absRotation = abs(rotation)
var newAbsRotation = abs(absRotation - strongSelf.initialRotation!)
if absRotation > strongSelf.initialRotation! {
newAbsRotation *= -1
}
//printDebug("newAbsRoll = \(newAbsRoll), pitch = \(pitch), newAbsRotation = \(newAbsRotation)")
globalMainQueue.async {
strongSelf.delegate?.updatedMotion(roll: newAbsRoll, pitch: pitch, yaw: newAbsRotation)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果需要任何澄清,请随时询问。
| 归档时间: |
|
| 查看次数: |
509 次 |
| 最近记录: |