Detect acceleration in absolute vertical axis

时光总嘲笑我的痴心妄想 提交于 2019-12-13 20:28:50

问题


I'm writing an app in which I want to access the acceleration data in an absolute vertical axis (i.e., from the ground to the floor), but with CoreMotion I'm only able to retrieve acceleration from the device's relative axis. For example if the device is laying flat on the table, it's vertical axis is actually at 90º from the absolute vertical axis.

I've been playing with the gyro data to try to fix this, but data don't make sense.

// Make sure the accelerometer hardware is available.
    if self.motion.isAccelerometerAvailable && self.motion.isDeviceMotionAvailable {
        self.motion.accelerometerUpdateInterval = 1.0 / Double(slider.value)  // Hz managed by slider
        self.motion.startAccelerometerUpdates()
        self.motion.startDeviceMotionUpdates(using: self.motion.attitudeReferenceFrame)
        self.motion.deviceMotionUpdateInterval = 1.0 / Double(slider.value)



        // Configure a timer to fetch the data.
        self.timer = Timer(fire: Date(), interval: (1.0/Double(slider.value)),
                           repeats: true, block: { (timer) in
                            // Get the gyroscope data.

                            if let data = self.motion.deviceMotion {
                                //Angles: pitch
                                pitch = data.attitude.pitch
                                print("Pitch angle: \(self.degrees(radians: pitch))")

                                    //Angles: yaw
                                yaw = data.attitude.yaw
                                print("Yaw angle: \(self.degrees(radians: yaw))")
                            }

                            //Get the accelerometer data

                            if let data = self.motion.accelerometerData {
                                let x = data.acceleration.x
                                //let y = data.acceleration.y
                                //let z = data.acceleration.z


                                // Use the accelerometer data in your app.
                                self.label.text = "x: \(x)"
                                let xCorrectedWithPitch = cos(self.degrees(radians: pitch)) * x
                                print("x: \(x)\nPitch: \(pitch)\nxCorrectedWithPitch: \(xCorrectedWithPitch)")
                                let xCorrectedWithYaw = cos(self.degrees(radians: yaw)) * xCorrectedWithPitch
                                print("x: \(x)\nYaw: \(yaw)\nxCorrectedWithYaw: \(xCorrectedWithYaw)")

                                // Use the accelerometer data in your app.

                                self.accelArrayY.append(xCorrectedWithYaw*9.81)
                                time = time + timer.timeInterval
                                self.timeArrayY.append(time)


                            }

Anyone help would be much appreciated


回答1:


CMMotionMagager gives you acceleration about the iPhone's axes and also the direction of gravity. By multiplying these two you can calculate the acceleration from/to the earth. It's the length of the result of this multiplication. I'm using Ray Wenderlich's 3D Vector utils.

In your GameViewController:

  var motionManager: CMMotionManager!

In GameViewController.viewDidLoad:

  motionManager = CMMotionManager()
  motionManager.startDeviceMotionUpdates()

In GameScene:

 override func update(_ currentTime: TimeInterval) {

    if let deviceMotion = motionManager.deviceMotion {

    let gravityVector = Vector3(x: CGFloat(deviceMotion.gravity.x),
                                y: CGFloat(deviceMotion.gravity.y),
                                z: CGFloat(deviceMotion.gravity.z))

    let userAccelerationVector = Vector3(x: CGFloat(deviceMotion.userAcceleration.x),
                                         y: CGFloat(deviceMotion.userAcceleration.y),
                                         z: CGFloat(deviceMotion.userAcceleration.z))

    // Acceleration to/from earth
    let zVector = gravityVector * userAccelerationVector
    let zAcceleration = zVector.length()
  }

To know the direction of movement:

sign(Double(zVector.x * zVector.y * zVector.z))

Don't forget to call .stopDeviceMotionUpdates() when you don't need it anymore.



来源:https://stackoverflow.com/questions/47073389/detect-acceleration-in-absolute-vertical-axis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!