Longitude / Latitude to quaternion
Asked Answered
I

3

6

I've got a longitude and latitude and want to convert this to a quaternion and wondering how I can do this? I want to use this, because I've got an app which projects the earth on a sphere and I want to rotate from one location to another one.

Best!

Instrument answered 25/3, 2011 at 20:36 Comment(0)
M
6

There's a way to go about this without using matrices or vectors, similar to this numpy implementation. We can think of longitude/latitude as two quaternion rotations composed together.

Let's work with a Z-up right-handed coordinate system. Let's call longitude φ and latitude θ, and the point represented by the two as (φ, θ). For visualization, the red axis corresponds to X, green to Y, and blue to Z.

We want to find the quaternion representing the rotation from (0, 0), in red, to (a, b), in green:

Sphere with origin and destination points

We can represent this rotation as a combination first of the longitudinal rotation, then of the latitudinal rotation, like so:

First rotation Second rotation

First, we rotated by a along the Z axis, which transforms the X and Y axes. Then, we rotated by b along the new local Y axis. Thus, we know two sets of axis/angle information for this rotation.

Luckily, the conversion from axis/angle to quaternions is already known. Given an angle α and an axis vector ω, the resulting quaternion is:

(cos(α/2), ω.x*sin(α/2), ω.y*sin(α/2), ω.z*sin(α/2))

So the first rotation is represented by a rotation of a degrees along the world (0, 0, 1) axis, giving us:

q1 = (cos(a/2), 0, 0, sin(a/2))

The second rotation is represented by a rotation of b degrees along the transformed/local (0, 1, 0) axis, giving us:

q2 = (cos(b/2), 0, sin(b/2), 0)

We can multiply these two quaternions to give us a single quaternion representing this compound rotation from (0, 0) to (a, b). The formula for quaternion multiplication is a bit lengthy, but you can find it here. The result:

q2*q1 = (cos(a/2)cos(b/2), -sin(a/2)sin(b/2), cos(a/2)sin(b/2), sin(a/2)cos(b/2))

Not that it means much, but we can confirm that this formula is the same as the numpy implementation mentioned before.

JCooper mentioned a great point that one degree of freedom is still left, along the X axis in this case. If θ stays within ±90 degrees, we can imagine that the Z axis always pointing upwards. This has the effect of constraining the X axis rotation and is hopefully what you want.

Hope this helps!


edit: Notice that this is essentially the same thing as working with 2 Euler angles. So to reverse this conversion, you can use any quaternion to Euler angle conversion, provided that the rotation order is the same.

Mithridate answered 14/11, 2017 at 5:1 Comment(2)
Im confused by "The second rotation is represented by a rotation of b degrees along the transformed/local (0, 1, 0) axis", if it is the local transformed axis why would the local (0,1,0) be the same as the world?Anti
@Anti How are you reading that the local (0, 1, 0) is the same as the world? It shouldn't be the case. Let me know if there's a point I can clarify.Mithridate
S
2

Latitude and longitude aren't enough to describe a quaternion. Latitude and longitude can describe a point on the surface of a 3d sphere. Let's say that's the point whose normal points directly out through the screen. You still have a degree of freedom left. The sphere can spin around the normal vector of the point specified by lat-lon. If you want a quaternion that represents the orientation of the sphere, you need to fully specify the rotation.

So let's say that you want to keep the north-pole of the sphere pointed upward. If the north pole is aligned with the object's +z axis and 'up' on the screen is aligned with the world's +y axis, and then you want to rotate the sphere so that point R on the surface of the sphere is pointed directly out at the screen (where R is found using lat-lon to euclidean as you mentioned in your comment), then you create the rotation matrix as follows.

You want object's R to align with the world's +z (assuming an OpenGL-like view-coordinate system) and you want object's +z to align with world's +y (as close as possible). We need the third axis; so we normalize R and then find: P = crossP([0 0 1]^T,R). We normalize P and then enforce orthogonality onto the second axis: Q = crossP(R,P). Finally, normalize Q. Now we have 3 orthogonal vectors P, Q, R that we want to align with the world's x,y,z respectively.

I'm assuming that P, Q, and R are column vectors; so to create a transformation matrix, we just stick 'em together: M = [P Q R]. Now M is the matrix that would transform a point in world coordinates into object coordinates. To go the opposite direction, we find the inverse of M. Fortunately, when the columns of a matrix are orthonormal, the inverse is the same as the transpose. So we get:

             [ P^T ]
M^-1 = M^T = [ Q^T ]
             [ R^T ]

From that, if you need, you can find a quaternion using matrix to quaternion conversion. And then you can interpolate between quaternions using slerp or your method of choice.

Skyjack answered 6/5, 2011 at 15:9 Comment(0)
W
1

Maybe you could look into how the boost C++ library implements it. (or perhaps even using it) http://www.boost.org/doc/libs/1_46_0/libs/math/doc/quaternion/html/boost_quaternions/quaternions/create.html

Longitude and lattitude are pretty much analogous to the azimuth (theta - [0, 2*PI]) and inclination (rho? [0,PI]) angles in spherical coordinates (radius r=1 of course for surface). Boost has a function for spherical to quaternion in the link i posted.

Wyly answered 25/3, 2011 at 20:49 Comment(4)
hi jon_darkstar, so longitude is phi, latitude is theta, but what would rho be?Instrument
its phi then? i forgot which =P its been a while since ive used spherical coordinates. i cant really picture what a third angle would do. rho could just be magnitude, but then why two phis? i cant help you much more than pointing you to that, good luckWyly
I'm using this to convert from latitude/longitude to cartesian coordinates: ' float phi = ofDegToRad(ll.lat + 90); float theta = ofDegToRad(ll.lon - 90); x = sin(phi) * cos(theta); y = sin(phi) * sin(theta); z = cos(phi);' now I need a way to turn this in to a rotation instead of a coordinate. The rotation can be in axis/angle or quaternion.Instrument
im probably missing something, but doesnt cartesian take you further away from what you need? latitude and longitude are anglesWyly

© 2022 - 2024 — McMap. All rights reserved.