Difference between revisions of "Quaternion"
(added 120º and 22.5º examples) |
Cholmondely (talk | contribs) (Added picture!) |
||
(22 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
+ | [[File:Quaternion Eagle.jpg|thumb|right|400px|A "Quaternion Eagle" from the Holy Roman Empire (each quaternion being represented by four coats of arms on the imperial eagle's remiges) Hans Burgkmair, c. 1510. Twelve quaternions are shown, as follows (eight dukes being divided into two quaternions called "pillars" and "vicars", respectively): Seill ("pillars"), Vicari ("vicars"), Marggrauen (margraves), Lantgrauen (landgraves), Burggrauen (burggraves), Grauen (counts), Semper freie (nobles), Ritter (knights), Stett (cities), Dörfer (villages), Bauern (peasants), Birg (castles).]] | ||
+ | == Definition == | ||
+ | |||
+ | In mathematics, the '''quaternion''' extends the complex numbers. Quaternions were first described by Irish mathematician William Rowan Hamilton in 1843 and applied to mechanics in three-dimensional space. Hamilton defined a quaternion as the quotient of two ''directed lines'' in a three-dimensional space, or, equivalently, as the quotient of two vectors. Multiplication of quaternions is noncommutative ('''i''' x '''j''' <font color="Red"> ≠ </font> '''j''' x '''i'''). | ||
+ | |||
+ | Quaternions are generally represented in the form | ||
+ | ''a'' + ''b'' '''i''' + ''c'' '''j''' + ''d'' '''k''' | ||
+ | |||
+ | where ''a'', ''b'', ''c'', and ''d'' are ''real numbers''; whilst '''i''', '''j''', and '''k''' are the ''basic quaternions''. | ||
+ | |||
+ | Quaternions are used in pure mathematics, but also have practical uses in applied mathematics, particularly for calculations involving three-dimensional rotations, such as in three-dimensional computer graphics, computer vision, and crystallographic texture analysis. They can be used alongside other methods of rotation, such as Euler angles and rotation matrices, or as an alternative to them, depending on the application. | ||
+ | :::::::::::::::from [https://en.wikipedia.org/wiki/Quaternion Wikipedia] | ||
+ | |||
+ | === Comment === | ||
+ | So what are quaternions? The quick and dirty answer is they are an alternate form of axis-angle rotations that lives in 'rotation space'. Like matrices, they can accumulate -- that is, you can chain them together indefinitely without any problems like gimbal lock. However, unlike matrices, they can smoothly interpolate from one orientation to another. | ||
+ | |||
+ | Are quaternions just better than all the other rotation formats? So far, they seem to combine all of their strengths. Unfortunately, they have two major weaknesses that ensure that they are only useful as intermediate rotations. First, they have no easy mapping to 3D space, so you will always create rotations in a more user-friendly format and convert it over. Second, they cannot efficiently rotate points, so you have to convert them to matrices in order to rotate significant numbers of points. | ||
+ | |||
+ | This means you will likely never start or end a series of rotations with a quaternion, but they can do intermediate processing more efficiently than any other format. | ||
+ | |||
+ | The internal workings of quaternions are not really intuitive or interesting to me, and probably won't be for you either if you're not a mathematician, so I advise finding libraries or functions online that wrap quaternions in a way that makes them easy to use. The Bullet or Blender math libraries could be a good place to start, and there are many others on the Internet. | ||
+ | |||
+ | :::::::::::::::from [http://blog.wolfire.com/2010/07/Linear-algebra-for-game-developers-part-4 Linear algebra for game developers] | ||
+ | |||
== Overview == | == Overview == | ||
Line 4: | Line 28: | ||
A quaternion is a set of four values (W X Y Z) that are used in Oolite to specify a rotation in 3D space. To specify a particular rotation you need to think about the axis about which the rotation is made and the angle or amount by which the model is to be rotated. | A quaternion is a set of four values (W X Y Z) that are used in Oolite to specify a rotation in 3D space. To specify a particular rotation you need to think about the axis about which the rotation is made and the angle or amount by which the model is to be rotated. | ||
− | For a given axis (x y z) and angle ( | + | For a given axis (x y z) and angle (α), the quaternion representing a rotation of a degrees around the axis from the origin (0,0,0) to (x,y,z) is: |
− | W = | + | W = cos (0.5 × α) |
− | X = x | + | X = x × sin (0.5 × α) |
− | Y = y | + | Y = y × sin (0.5 × α) |
− | Z = z | + | Z = z × sin (0.5 × α) |
Line 19: | Line 43: | ||
− | W = | + | W = cos 45 ° = 0.707… |
− | X = 0 | + | X = 0 × sin 45 ° = 0 |
− | Y = 0 | + | Y = 0 × sin 45 ° = 0 |
− | Z = 1 | + | Z = 1 × sin 45 ° = 0.707… |
− | Now because quaternions are normalised (adjusted so that W | + | Now because quaternions are normalised (adjusted so that W × W + X × X + Y × Y + Z × Z = 1) when Oolite reads them in, you can multiply each part of a quaternion by the same value and still have it represent the same angle. So this rotation can also be represented as W = 1, X = 0, Y = 0, Z = 1 (let's use [1 0 0 1] as shorthand). |
== Examples == | == Examples == | ||
− | === | + | === 90 ° turns about the z-axis === |
− | Oolite uses quaternions to specify rotations in some parts of [[shipdata.plist]], most notably in the subentities part of an entry, like here in the relevant sub-entity entry for [[ | + | Oolite uses quaternions to specify rotations in some parts of [[shipdata.plist]], most notably in the subentities part of an entry, like here in the relevant sub-entity entry for the [[Coriolis station (Oolite)|Coriolis station]]: |
Code: | Code: | ||
− | + | subentities = | |
− | + | ( | |
− | + | "arc-detail 0 0 0 1 0 0 0", | |
− | + | "arc-detail 0 0 0 1 0 0 1", | |
− | + | "arc-detail 0 0 0 0 0 0 1" | |
− | + | "arc-detail 0 0 0 1 0 0 -1" | |
− | + | ) | |
The last four numbers after the four 'arc-detail' lines are the W X Y and Z of quaternions representing rotations about the z-axis of 0 degrees, 90 degrees, 180 degrees, and 270 degrees (the first three numbers are the subentity's position relative to the station, in this case all are at the same place at the station's origin). | The last four numbers after the four 'arc-detail' lines are the W X Y and Z of quaternions representing rotations about the z-axis of 0 degrees, 90 degrees, 180 degrees, and 270 degrees (the first three numbers are the subentity's position relative to the station, in this case all are at the same place at the station's origin). | ||
+ | === 120 ° turns about the z-axis === | ||
+ | |||
+ | Similarly, the shipdata of the [[Weeviloid_Hunter|Weeviloid 2]] illustrates how to place sub-entities at 3 equilateral points: | ||
+ | |||
+ | |||
+ | Code: | ||
+ | subentities = | ||
+ | ( | ||
+ | "weeviloid2-spine 0 0 0 1 0 0 0", | ||
+ | "weeviloid2-spine 0 0 0 0.5 0 0 0.8660254", | ||
+ | "weeviloid2-spine 0 0 0 0.5 0 0 -0.8660254" | ||
+ | ) | ||
+ | |||
+ | |||
+ | Given that the first entry (0 0 0 1 0 0 0) will place the sub-entity at the exact place that the model is situated (0 degrees), the next two lines reproduce it at 120 degrees and 240 degrees. | ||
− | === | + | === 22.5 ° turns about the z-axis === |
− | + | To display 16 sub-entities that join to make a ring, as done in the [[Ringpod]] and [[Torus station|Torus]] shipdata, these are the relevant lines: | |
Code: | Code: | ||
− | + | subentities = | |
− | + | ( | |
− | + | "torus_pod 0 0 0 1 0 0 0", // 0 degree | |
− | + | "torus_pod 0 0 0 0.9808 0.0 0.0 0.1951", // 22.5 degrees | |
− | + | "torus_pod 0 0 0 0.9239 0.0 0.0 0.3827", // 45 degrees | |
− | + | "torus_pod 0 0 0 0.8315 0.0 0.0 0.5556", / /67.5 degrees | |
+ | "torus_pod 0 0 0 0.7071 0.0 0.0 0.7071", // 90 degrees | ||
+ | "torus_pod 0 0 0 0.5556 0.0 0.0 0.83110", //112.5 degrees | ||
+ | "torus_pod 0 0 0 0.3827 0.0 0.0 0.9239", // 135 degrees | ||
+ | "torus_pod 0 0 0 0.1951 0.0 0.0 0.9808", // 157.5 degrees | ||
+ | "torus_pod 0 0 0 0 0 0 1", // 180 degrees | ||
+ | "torus_pod 0 0 0 -0.1951 0.0 0.0 0.9808", // 202.5 degrees | ||
+ | "torus_pod 0 0 0 -0.3827 0.0 0.0 0.9239", // 225 degrees | ||
+ | "torus_pod 0 0 0 -0.5556 0.0 0.0 0.83110", // 247.5 degrees | ||
+ | "torus_pod 0 0 0 -0.7071 0.0 0.0 0.7071", // 270 degrees | ||
+ | "torus_pod 0 0 0 -0.8315 0.0 0.0 0.5556", // 292.5 degrees | ||
+ | "torus_pod 0 0 0 -0.9239 0.0 0.0 0.3827", // 315 degrees | ||
+ | "torus_pod 0 0 0 -0.9808 0.0 0.0 0.1951" // 337.5 degrees | ||
+ | ) | ||
+ | |||
+ | |||
+ | Again the 0 ° sub-entity will appear with the 0 0 0 1 0 0 0, and the next 15 lines place it at 22.5 °, 45 °, 67.5 °, 90 °, 112.5 °, 135 °, 157.5 °, 180 ° (with 0 0 0 0 0 0 1), 202.5 °, 225 °, 247.5 °, 270 °, 292.5 °, 315 ° and 337.5 °. | ||
+ | |||
+ | === using Java Script to calculate quaternions === | ||
+ | |||
+ | Oolite contains a whole set of vector and quaternion methods than can be used for easy manipulating quaternions. To generate a quaternion for a certain rotation around the z-axis we can rotate the identity quaternion around the z-axis with the command: | ||
+ | new Quaternion(1,0,0,0).rotate(new Vector3D(0,0,1), angle) | ||
+ | With this command we can calculate our own quaternion for any rotation around the z-axis, or any other axis when desired. Angle is not in degree but in Math.PI | ||
+ | |||
+ | === Quaternion calculus === | ||
+ | |||
+ | To perform one rotation, and then another, one needs to multiply two quaternions together. | ||
+ | |||
+ | Multiplying quaternions isn't commutative: Qa × Qb does not equal Qb × Qa | ||
+ | |||
+ | To multiply Q₁ (w₁ , x₁ , y₁ , z₁ ) by Q₂ (w₂, x₂, y₂, z₂): | ||
+ | |||
+ | W = w₁ × w₂ - x₁ × x₂ - y₁ × y₂ - z₁ × z₂ | ||
+ | |||
+ | X = w₁ × x₂ + x₁ × w₂ + y₁ × z₂ - z₁ × y₂ | ||
+ | |||
+ | Y = w₁ × y₂ + y₁ × w₂ + z₁ × x₂ - x₁ × z₂ | ||
+ | |||
+ | Z = w₁ × z₂ + z₁ × w₂ + x₁ × y₂ - y₁ × x₂ | ||
+ | |||
+ | |||
+ | To determine the quaternion for a rotation of α degrees/radians around an axis defined by a vector (x, y, z): | ||
+ | |||
+ | W = cos (0.5 × α) | ||
+ | |||
+ | X = x × sin (0.5 × α) | ||
+ | Y = y × sin (0.5 × α) | ||
− | + | Z = z × sin (0.5 × α) | |
+ | ''or'': | ||
− | = | + | W = 1 / tan (0.5 × α) |
− | + | X = x | |
+ | Y = y | ||
− | + | Z = z | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | These are equivalent because of the trigonometric identity sin x/cos x = tan x, and the fact that quaternion normalization means that multiplying each component by the same value (in this case, 1 / sin (0.5 × α)) does not affect the resulting orientation. | ||
− | + | === Oolite Specifics === | |
+ | Although Quaternions are coordinate system indifferent, Oolite, because it makes use of OpenGL, uses a [http://en.wikipedia.org/wiki/Left-handed_coordinate_system#Orientation_and_handedness left-handed coordinate system]. This means that all positive quaternion rotations about an axis, as discussed in the [[#Overview|Overview]] section above, are anti-clockwise (counter-clockwise) when the axis of rotation is pointing towards you (clockwise if pointing away from you). | ||
+ | Also all Oolite ships and other entities have to be designed with forwards pointing along the z-axis, up along the y-axis and right along the x-axis. These entities have an orientation in space is given by a quaternion (the [[Oolite_JavaScript_Reference:_Entity#orientation|.orientation]] JavaScript property) that describes the transformation from this initial design orientation to the required final orientation. | ||
− | == | + | == See Also == |
+ | * [[Oolite JavaScript Reference: Quaternion]] | ||
+ | * [https://app.box.com/s/6usw7ozbvobze3hkouzc Quaternion calculator] - a very useful spreadsheet | ||
* [http://en.wikipedia.org/wiki/Quaternion Wikipedia page on quaternions] | * [http://en.wikipedia.org/wiki/Quaternion Wikipedia page on quaternions] | ||
+ | * [http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation Wikipedia page on quaternions and spatial rotation] | ||
* [http://skal.planet-d.net/demo/matrixfaq.htm The Matrix and Quaternion FAQ] | * [http://skal.planet-d.net/demo/matrixfaq.htm The Matrix and Quaternion FAQ] | ||
+ | * [http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/program/index.htm Maths - Axis-Angle to Quaternion - Program ] | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
− | [[Category:Oolite]] | + | [[Category:Oolite scripting]] |
Latest revision as of 10:14, 5 March 2023
Contents
Definition
In mathematics, the quaternion extends the complex numbers. Quaternions were first described by Irish mathematician William Rowan Hamilton in 1843 and applied to mechanics in three-dimensional space. Hamilton defined a quaternion as the quotient of two directed lines in a three-dimensional space, or, equivalently, as the quotient of two vectors. Multiplication of quaternions is noncommutative (i x j ≠ j x i). Quaternions are generally represented in the form a + b i + c j + d k where a, b, c, and d are real numbers; whilst i, j, and k are the basic quaternions. Quaternions are used in pure mathematics, but also have practical uses in applied mathematics, particularly for calculations involving three-dimensional rotations, such as in three-dimensional computer graphics, computer vision, and crystallographic texture analysis. They can be used alongside other methods of rotation, such as Euler angles and rotation matrices, or as an alternative to them, depending on the application.
- from Wikipedia
Comment
So what are quaternions? The quick and dirty answer is they are an alternate form of axis-angle rotations that lives in 'rotation space'. Like matrices, they can accumulate -- that is, you can chain them together indefinitely without any problems like gimbal lock. However, unlike matrices, they can smoothly interpolate from one orientation to another.
Are quaternions just better than all the other rotation formats? So far, they seem to combine all of their strengths. Unfortunately, they have two major weaknesses that ensure that they are only useful as intermediate rotations. First, they have no easy mapping to 3D space, so you will always create rotations in a more user-friendly format and convert it over. Second, they cannot efficiently rotate points, so you have to convert them to matrices in order to rotate significant numbers of points.
This means you will likely never start or end a series of rotations with a quaternion, but they can do intermediate processing more efficiently than any other format.
The internal workings of quaternions are not really intuitive or interesting to me, and probably won't be for you either if you're not a mathematician, so I advise finding libraries or functions online that wrap quaternions in a way that makes them easy to use. The Bullet or Blender math libraries could be a good place to start, and there are many others on the Internet.
Overview
A quaternion is a set of four values (W X Y Z) that are used in Oolite to specify a rotation in 3D space. To specify a particular rotation you need to think about the axis about which the rotation is made and the angle or amount by which the model is to be rotated.
For a given axis (x y z) and angle (α), the quaternion representing a rotation of a degrees around the axis from the origin (0,0,0) to (x,y,z) is:
W = cos (0.5 × α)
X = x × sin (0.5 × α)
Y = y × sin (0.5 × α)
Z = z × sin (0.5 × α)
So a rotation of 90 degrees about the z axis (0 0 1) would be:
W = cos 45 ° = 0.707…
X = 0 × sin 45 ° = 0
Y = 0 × sin 45 ° = 0
Z = 1 × sin 45 ° = 0.707…
Now because quaternions are normalised (adjusted so that W × W + X × X + Y × Y + Z × Z = 1) when Oolite reads them in, you can multiply each part of a quaternion by the same value and still have it represent the same angle. So this rotation can also be represented as W = 1, X = 0, Y = 0, Z = 1 (let's use [1 0 0 1] as shorthand).
Examples
90 ° turns about the z-axis
Oolite uses quaternions to specify rotations in some parts of shipdata.plist, most notably in the subentities part of an entry, like here in the relevant sub-entity entry for the Coriolis station:
Code:
subentities =
( "arc-detail 0 0 0 1 0 0 0", "arc-detail 0 0 0 1 0 0 1", "arc-detail 0 0 0 0 0 0 1" "arc-detail 0 0 0 1 0 0 -1" )
The last four numbers after the four 'arc-detail' lines are the W X Y and Z of quaternions representing rotations about the z-axis of 0 degrees, 90 degrees, 180 degrees, and 270 degrees (the first three numbers are the subentity's position relative to the station, in this case all are at the same place at the station's origin).
120 ° turns about the z-axis
Similarly, the shipdata of the Weeviloid 2 illustrates how to place sub-entities at 3 equilateral points:
Code:
subentities = ( "weeviloid2-spine 0 0 0 1 0 0 0", "weeviloid2-spine 0 0 0 0.5 0 0 0.8660254", "weeviloid2-spine 0 0 0 0.5 0 0 -0.8660254" )
Given that the first entry (0 0 0 1 0 0 0) will place the sub-entity at the exact place that the model is situated (0 degrees), the next two lines reproduce it at 120 degrees and 240 degrees.
22.5 ° turns about the z-axis
To display 16 sub-entities that join to make a ring, as done in the Ringpod and Torus shipdata, these are the relevant lines:
Code:
subentities = ( "torus_pod 0 0 0 1 0 0 0", // 0 degree "torus_pod 0 0 0 0.9808 0.0 0.0 0.1951", // 22.5 degrees "torus_pod 0 0 0 0.9239 0.0 0.0 0.3827", // 45 degrees "torus_pod 0 0 0 0.8315 0.0 0.0 0.5556", / /67.5 degrees "torus_pod 0 0 0 0.7071 0.0 0.0 0.7071", // 90 degrees "torus_pod 0 0 0 0.5556 0.0 0.0 0.83110", //112.5 degrees "torus_pod 0 0 0 0.3827 0.0 0.0 0.9239", // 135 degrees "torus_pod 0 0 0 0.1951 0.0 0.0 0.9808", // 157.5 degrees "torus_pod 0 0 0 0 0 0 1", // 180 degrees "torus_pod 0 0 0 -0.1951 0.0 0.0 0.9808", // 202.5 degrees "torus_pod 0 0 0 -0.3827 0.0 0.0 0.9239", // 225 degrees "torus_pod 0 0 0 -0.5556 0.0 0.0 0.83110", // 247.5 degrees "torus_pod 0 0 0 -0.7071 0.0 0.0 0.7071", // 270 degrees "torus_pod 0 0 0 -0.8315 0.0 0.0 0.5556", // 292.5 degrees "torus_pod 0 0 0 -0.9239 0.0 0.0 0.3827", // 315 degrees "torus_pod 0 0 0 -0.9808 0.0 0.0 0.1951" // 337.5 degrees )
Again the 0 ° sub-entity will appear with the 0 0 0 1 0 0 0, and the next 15 lines place it at 22.5 °, 45 °, 67.5 °, 90 °, 112.5 °, 135 °, 157.5 °, 180 ° (with 0 0 0 0 0 0 1), 202.5 °, 225 °, 247.5 °, 270 °, 292.5 °, 315 ° and 337.5 °.
using Java Script to calculate quaternions
Oolite contains a whole set of vector and quaternion methods than can be used for easy manipulating quaternions. To generate a quaternion for a certain rotation around the z-axis we can rotate the identity quaternion around the z-axis with the command:
new Quaternion(1,0,0,0).rotate(new Vector3D(0,0,1), angle)
With this command we can calculate our own quaternion for any rotation around the z-axis, or any other axis when desired. Angle is not in degree but in Math.PI
Quaternion calculus
To perform one rotation, and then another, one needs to multiply two quaternions together.
Multiplying quaternions isn't commutative: Qa × Qb does not equal Qb × Qa
To multiply Q₁ (w₁ , x₁ , y₁ , z₁ ) by Q₂ (w₂, x₂, y₂, z₂):
W = w₁ × w₂ - x₁ × x₂ - y₁ × y₂ - z₁ × z₂
X = w₁ × x₂ + x₁ × w₂ + y₁ × z₂ - z₁ × y₂
Y = w₁ × y₂ + y₁ × w₂ + z₁ × x₂ - x₁ × z₂
Z = w₁ × z₂ + z₁ × w₂ + x₁ × y₂ - y₁ × x₂
To determine the quaternion for a rotation of α degrees/radians around an axis defined by a vector (x, y, z):
W = cos (0.5 × α)
X = x × sin (0.5 × α)
Y = y × sin (0.5 × α)
Z = z × sin (0.5 × α)
or:
W = 1 / tan (0.5 × α)
X = x
Y = y
Z = z
These are equivalent because of the trigonometric identity sin x/cos x = tan x, and the fact that quaternion normalization means that multiplying each component by the same value (in this case, 1 / sin (0.5 × α)) does not affect the resulting orientation.
Oolite Specifics
Although Quaternions are coordinate system indifferent, Oolite, because it makes use of OpenGL, uses a left-handed coordinate system. This means that all positive quaternion rotations about an axis, as discussed in the Overview section above, are anti-clockwise (counter-clockwise) when the axis of rotation is pointing towards you (clockwise if pointing away from you).
Also all Oolite ships and other entities have to be designed with forwards pointing along the z-axis, up along the y-axis and right along the x-axis. These entities have an orientation in space is given by a quaternion (the .orientation JavaScript property) that describes the transformation from this initial design orientation to the required final orientation.
See Also
- Oolite JavaScript Reference: Quaternion
- Quaternion calculator - a very useful spreadsheet
- Wikipedia page on quaternions
- Wikipedia page on quaternions and spatial rotation
- The Matrix and Quaternion FAQ
- Maths - Axis-Angle to Quaternion - Program