Please help me apply device rotation data correctly.

So, I have a little project that I am trying to do. I am trying to get the rotation of the devices relative to gravity and translation from the place where it started. Thus, basically getting "tracking" data for the device. I plan to mainly apply this by making 3d pt, which will simulate the data that I write from the device later.

In any case, in order to try to achieve this, I thought it was best to work with a set of plots so that I could see things in three dimensions in the same way as the data I was trying to record. Right now I'm trying to make the ship rotate so that it always looks like this (for example, it is on the ground or something else), so that the device does not rotate. I believe that when I do this, it will be a sich to apply this to a point. So I made the following code:

if let attitude = motionManager.deviceMotion?.attitude { print(attitude) ship.eulerAngles.y = -Float(attitude.roll) ship.eulerAngles.z = -Float(attitude.yaw) ship.eulerAngles.x = -Float(attitude.pitch) } 

When you start only one of the lines of rotation, everything is fine. He behaves correctly on this axis. However, when I do all three axes, it immediately becomes chaotic and performs far from expected with trembling and all.

I think my question is: Does anyone know how to fix my code above so that the ship remains correctly "vertical", regardless of orientation.

+5
source share
1 answer

J.doe!

First there is a little trick. If you want to use iphone as the default position, you should notice that the axes used in sceneKit are different from the axes used by DeviceMotion. Check axis:

deviceMotion axis sceneKit axis
(source: apple.com )

The first thing you need to install is the position of the camera. When you start the SceneKit project, it creates your camera at (0, 0, 15). There is a problem with this:

The values ​​eulerAngles = (0,0,0) mean that the object will be in the xz plane, but while you look at Z, you just see it from the side. In order for this to be equivalent to an iphone, you must set up the camera so that it is viewed from above. So you would look at it from the phone (like a camera, idk)

 // create and add a camera to the scene let cameraNode = SCNNode() cameraNode.camera = SCNCamera() scene.rootNode.addChildNode(cameraNode) // place the camera cameraNode.position = SCNVector3(x: 0, y: 15, z: 0) // but then you need to make the cameraNode face the ship (the origin of the axis), rotating it cameraNode.eulerAngles.x = -Float(M_PI)*0.5 //or Float(M_PI)*1.5 

With this we will see the ship from above, so the first part is done. Now we have to make the ship remain “motionless” (facing the ground) while rotating the device.

 //First we need to use SCNRendererDelegate class GameViewController : UIViewController SCNSceneRendererDelegate{ private let motion = CMMotionManager(); ... 

Then on viewDidLoad:

 //important if you remove the sceneKit initial action from the ship. //The scene would be static, and static scenes do not trigger the renderer update, setting the playing property to true forces that: scnView.playing = true; if(motion.deviceMotionAvailable){ motion.startDeviceMotionUpdates(); motion.deviceMotionUpdateInterval = 1.0/60.0; } 

Then we go to the update method

Look at the axis: the Y axis and the Z axis "switch" when comparing the sceneKit axis and the device axis device. Z is on the phone, and is on the side of the scene, and Y is on the stage, and on the side of the phone. Thus, pitch, roll and yaw, respectively associated with the X, Y, and Z axes, will be applied as pitch, yaw, and roll.

Please note that I set the roll value to positive because there is something else “switched”. It is rather difficult to visualize. See, the Y axis of the device’s movement correlates with the Z axis of the scene. Now imagine that the objects rotate along this axis in the same direction (for example, clockwise), they will move in opposite directions due to the location of the axis. (you can also set a negative result on the roll to see how it goes wrong)

 func renderer(renderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) { if let rot = motion.deviceMotion?.attitude{ print("\(rot.pitch) \(rot.roll) \(rot.yaw)") ship.eulerAngles.x = -Float(rot.pitch); ship.eulerAngles.y = -Float(rot.yaw); ship.eulerAngles.z = Float(rot.roll); } 

Hope this helps! See you!

+9
source

Source: https://habr.com/ru/post/1234235/


All Articles