问题
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!
回答1:
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:
We can represent this rotation as a combination first of the longitudinal rotation, then of the latitudinal rotation, like so:
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.
回答2:
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.
回答3:
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.
来源:https://stackoverflow.com/questions/5437865/longitude-latitude-to-quaternion