Difference between revisions of "Oolite JavaScript Reference: Quaternion"
(Updated for 1.74.) |
(link to Quaternion calculator) |
||
(20 intermediate revisions by 5 users not shown) | |||
Line 10: | Line 10: | ||
* MathWorld: [http://mathworld.wolfram.com/Quaternion.html Quaternion] |
* MathWorld: [http://mathworld.wolfram.com/Quaternion.html Quaternion] |
||
− | Consider a ship at point ''h'' oriented to face a station at point ''t''. This can be expressed as the vector from the ship to the station, ''v'' = ''t'' − ''h''. However, if the ship rolls, it is still heading along the same vector ''v'', so additional information is required: a twist angle, ''α'' |
+ | Consider a ship at point ''h'' oriented to face a station at point ''t''. This can be expressed as the vector from the ship to the station, ''v'' = ''t'' − ''h''. However, if the ship rolls, it is still heading along the same vector ''v'', so additional information is required: a twist angle, ''α''. A rotation quaternion is a tuple ''Q'' = (''w'', ''x'', ''y'', ''z''), such that |
:''Q<sub>w</sub>'' = cos ''α''/2 |
:''Q<sub>w</sub>'' = cos ''α''/2 |
||
:''Q<sub>x</sub>'' = ''v<sub>x</sub>'' sin ''α''/2 |
:''Q<sub>x</sub>'' = ''v<sub>x</sub>'' sin ''α''/2 |
||
Line 17: | Line 17: | ||
Additionally, a rotation quaternion must be normalized; that is, it must fulfill the '''normal invariant''' ''Q<sub>w</sub>''² + ''Q<sub>x</sub>''² + ''Q<sub>y</sub>''² + ''Q<sub>z</sub>''² = 1. Unlike with [[property list]] scripting and specifications, quaternions will not be automatically normalized for you except where specified, but a <code>[[#normalize|normalize]]()</code> method is provided. |
Additionally, a rotation quaternion must be normalized; that is, it must fulfill the '''normal invariant''' ''Q<sub>w</sub>''² + ''Q<sub>x</sub>''² + ''Q<sub>y</sub>''² + ''Q<sub>z</sub>''² = 1. Unlike with [[property list]] scripting and specifications, quaternions will not be automatically normalized for you except where specified, but a <code>[[#normalize|normalize]]()</code> method is provided. |
||
− | An '''identity rotation''' – that is, one which, when applied, has no effect – is represented by the '''identity quaternion''' (1, 0, 0, 0). |
+ | An '''identity rotation''' – that is, one which, when applied, has no effect – is represented by the '''identity quaternion''' (1, 0, 0, 0). Often you will want to start with this identity quaternion before applying the methods '''rotate''', '''rotateX''', '''rotateY''' or '''rotateZ'''. |
The <code>Quaternion</code> class provides several methods to make construction of rotations easier: <code>[[#rotate|rotate]]()</code>, <code>[[#rotateX|rotateX]]()</code>, <code>[[#rotateY|rotateY]]()</code>, <code>[[#rotateZ|rotateZ]]()</code>. |
The <code>Quaternion</code> class provides several methods to make construction of rotations easier: <code>[[#rotate|rotate]]()</code>, <code>[[#rotateX|rotateX]]()</code>, <code>[[#rotateY|rotateY]]()</code>, <code>[[#rotateZ|rotateZ]]()</code>. |
||
Line 23: | Line 23: | ||
Rotations can be combined by quaternion multiplication (see the <code>[[#multiply|multiply]]()</code> method). Note that quaternion multiplication is not commutative; that is, ''PQ'' is not the same as ''QP''. If this seems strange, take a box or book and assign it ''x'', ''y'' and ''z'' axes. Rotate it about the ''x'' axis and then the ''y'' axis. Then, rotate it about the ''y'' axis followed by the ''x'' axis. If the results of the two rotations are the same, you’re doing it wrong. |
Rotations can be combined by quaternion multiplication (see the <code>[[#multiply|multiply]]()</code> method). Note that quaternion multiplication is not commutative; that is, ''PQ'' is not the same as ''QP''. If this seems strange, take a box or book and assign it ''x'', ''y'' and ''z'' axes. Rotate it about the ''x'' axis and then the ''y'' axis. Then, rotate it about the ''y'' axis followed by the ''x'' axis. If the results of the two rotations are the same, you’re doing it wrong. |
||
− | === Quaternion Expressions === |
||
+ | The [https://app.box.com/s/6usw7ozbvobze3hkouzc Quaternion calculator] is a very useful spreadsheet to get quaternions from rotation angles. |
||
− | All Oolite-provided functions which take a quaternion as an argument may instead be passed an [[Oolite JavaScript Reference: Entity|Entity]] instead, in which case the entity’s <code>[[Oolite JavaScript Reference: Entity#orientation|orientation]]</code> is used. In specifications, this is represented by arguments named <code>quaternionOrEntity</code>. (Is this actually useful? It seems less compellingly so than the [[Oolite JavaScript Reference: Vector#Vector Expressions|vector equivalent]]. -- [[User:Ahruman]]) |
||
− | Additionally, most <code>Quaternion</code> methods may be passed four numbers, or an array of four numbers, instead of a quaternion. In specifications, this is represented by arguments named <code>quaternionExpression</code>. |
||
+ | === Quaternion Expressions === |
||
+ | All Oolite-provided functions which take a quaternion as an argument may instead be passed an array of four numbers, or an [[Oolite JavaScript Reference: Entity|Entity]] (in which case the entity’s <code>[[Oolite JavaScript Reference: Entity#orientation|orientation]]</code> is used). In specifications, this is represented by arguments typed <code>quaternionExpression</code>. |
||
== Properties == |
== Properties == |
||
Line 49: | Line 49: | ||
=== Constructor === |
=== Constructor === |
||
'''new Quaternion'''([value : [[#Quaternion Expressions|quaternionExpression]]]) |
'''new Quaternion'''([value : [[#Quaternion Expressions|quaternionExpression]]]) |
||
− | Create a new quaternion with the specified value. If no value is provided, the |
+ | Create a new quaternion with the specified value. If no value is provided, the quaternion is initialized to the identity quaternion (1, 0, 0, 0). |
+ | |||
+ | ''Note'': in version 1.77 or earlier, the quaternion is incorrectly initialised to the zero quaternion ('''0''', 0, 0, 0) if no value is provided. For portability you should therefore provide a value to the constructor. |
||
+ | |||
+ | === <code>conjugate</code> === |
||
+ | {{oolite-method-added|1.77}} |
||
+ | function '''conjugate'''() : Quaternion |
||
+ | Return the conjugate of the quaternion (i.e. the quaternion which when multiplied by the original quaternion returns the identity quaternion). The input quaternion must be normalized. |
||
=== <code>dot</code> === |
=== <code>dot</code> === |
||
function '''dot'''(q : [[#Quaternion Expressions|quaternionExpression]]) : Number |
function '''dot'''(q : [[#Quaternion Expressions|quaternionExpression]]) : Number |
||
− | Returns the quaternion dot product (inner product) of the target and <code>q</code>. ( |
+ | Returns the quaternion dot product (inner product) of the target and <code>q</code>. (For two normalized quaternions, this will be 1 if they’re equal, -1 if they’re opposite and 0 if they’re perpendicular.) |
=== <code>multiply</code> === |
=== <code>multiply</code> === |
||
function '''multiply'''(q : [[#Quaternion Expressions|quaternionExpression]]) : Quaternion |
function '''multiply'''(q : [[#Quaternion Expressions|quaternionExpression]]) : Quaternion |
||
− | Returns the standard quaternion product ( |
+ | Returns the standard quaternion product (Grassmann product) of the target and <code>q</code>. This is used to concatenate rotations together. |
=== <code>normalize</code> === |
=== <code>normalize</code> === |
||
Line 65: | Line 65: | ||
=== <code>rotate</code> === |
=== <code>rotate</code> === |
||
function '''rotate'''(a : [[Oolite JavaScript Reference: Vector#Vector Expressions|vectorExpression]], angle : Number) : Quaternion |
function '''rotate'''(a : [[Oolite JavaScript Reference: Vector#Vector Expressions|vectorExpression]], angle : Number) : Quaternion |
||
− | Returns a quaternion rotated <code>angle</code> radians about the axis of <code>a</code>. |
+ | Returns a quaternion rotated <code>angle</code> radians about the axis of <code>a</code>. The vector <code>a</code> must be a normalized vector. A positive angle is anti-clockwise if the vector is pointing towards you. |
=== <code>rotateX</code> === |
=== <code>rotateX</code> === |
||
function '''rotateX'''(angle : Number) : Quaternion |
function '''rotateX'''(angle : Number) : Quaternion |
||
− | Returns a quaternion rotated <code>angle</code> radians about the ''x'' axis. |
+ | Returns a quaternion rotated <code>angle</code> radians about the ''x'' axis. A positive angle is anti-clockwise if the ''x'' axis is pointing towards you. |
− | <code>q.rotateX(angle)</code> is equivalent to <code>q.[[#rotate|rotate]](1, 0, 0, angle)</code>. |
+ | <code>q.rotateX(angle)</code> is equivalent to <code>q.[[#rotate|rotate]]([1, 0, 0], angle)</code>. |
=== <code>rotateY</code> === |
=== <code>rotateY</code> === |
||
function '''rotateY'''(angle : Number) : Quaternion |
function '''rotateY'''(angle : Number) : Quaternion |
||
− | Returns a quaternion rotated <code>angle</code> radians about the ''y'' axis. |
+ | Returns a quaternion rotated <code>angle</code> radians about the ''y'' axis. A positive angle is anti-clockwise if the ''y'' axis is pointing towards you. |
− | <code>q.rotateY(angle)</code> is equivalent to <code>q.[[#rotate|rotate]](0, 1, 0, angle)</code>. |
+ | <code>q.rotateY(angle)</code> is equivalent to <code>q.[[#rotate|rotate]]([0, 1, 0], angle)</code>. |
=== <code>rotateZ</code> === |
=== <code>rotateZ</code> === |
||
function '''rotateZ'''(angle : Number) : Quaternion |
function '''rotateZ'''(angle : Number) : Quaternion |
||
− | Returns a quaternion rotated <code>angle</code> radians about the ''z'' axis. |
+ | Returns a quaternion rotated <code>angle</code> radians about the ''z'' axis. A positive angle is anti-clockwise if the ''z'' axis is pointing towards you. |
− | <code>q.rotateZ(angle)</code> is equivalent to <code>q.[[#rotate|rotate]](0, 0, 1, angle)</code>. |
+ | <code>q.rotateZ(angle)</code> is equivalent to <code>q.[[#rotate|rotate]]([0, 0, 1], angle)</code>. |
=== <code>toArray</code> === |
=== <code>toArray</code> === |
||
Line 102: | Line 102: | ||
function '''vectorUp'''() : [[Oolite JavaScript Reference: Vector|Vector]] |
function '''vectorUp'''() : [[Oolite JavaScript Reference: Vector|Vector]] |
||
Returns the up vector from the quaternion. See <code>[[#vectorForward|vectorForward]]()</code> for a definition. |
Returns the up vector from the quaternion. See <code>[[#vectorForward|vectorForward]]()</code> for a definition. |
||
+ | |||
+ | == Static Methods == |
||
+ | |||
+ | === <code>random</code> === |
||
+ | function '''random'''() : Quaternion |
||
+ | Returns a random normalized quaternion. |
||
Latest revision as of 11:05, 20 June 2014
Prototype: Object
Subtypes: none
The Quaternion
class represents a quaternion, a four-dimensional number, which is used to express rotations. Explaining quaternion mathematics is way beyond the scope of this document, but a quick overview is provided below.
Contents
Quaternions for Rotations
This is a very quick, pragmatic discussion of quaternions as they apply to rotating things in Oolite. If you’re interested in the theory, see:
- Wikipedia: Quaternions and spatial rotation
- Wikipedia: Quaternion
- MathWorld: Quaternion
Consider a ship at point h oriented to face a station at point t. This can be expressed as the vector from the ship to the station, v = t − h. However, if the ship rolls, it is still heading along the same vector v, so additional information is required: a twist angle, α. A rotation quaternion is a tuple Q = (w, x, y, z), such that
- Qw = cos α/2
- Qx = vx sin α/2
- Qy = vy sin α/2
- Qz = vz sin α/2
Additionally, a rotation quaternion must be normalized; that is, it must fulfill the normal invariant Qw² + Qx² + Qy² + Qz² = 1. Unlike with property list scripting and specifications, quaternions will not be automatically normalized for you except where specified, but a normalize()
method is provided.
An identity rotation – that is, one which, when applied, has no effect – is represented by the identity quaternion (1, 0, 0, 0). Often you will want to start with this identity quaternion before applying the methods rotate, rotateX, rotateY or rotateZ.
The Quaternion
class provides several methods to make construction of rotations easier: rotate()
, rotateX()
, rotateY()
, rotateZ()
.
Rotations can be combined by quaternion multiplication (see the multiply()
method). Note that quaternion multiplication is not commutative; that is, PQ is not the same as QP. If this seems strange, take a box or book and assign it x, y and z axes. Rotate it about the x axis and then the y axis. Then, rotate it about the y axis followed by the x axis. If the results of the two rotations are the same, you’re doing it wrong.
The Quaternion calculator is a very useful spreadsheet to get quaternions from rotation angles.
Quaternion Expressions
All Oolite-provided functions which take a quaternion as an argument may instead be passed an array of four numbers, or an Entity (in which case the entity’s orientation
is used). In specifications, this is represented by arguments typed quaternionExpression
.
Properties
w
w : Number (read/write)
The w component of the quaternion.
x
x : Number (read/write)
The x component of the quaternion.
y
y : Number (read/write)
The y component of the quaternion.
z
z : Number (read/write)
The z component of the quaternion.
Methods
Constructor
new Quaternion([value : quaternionExpression])
Create a new quaternion with the specified value. If no value is provided, the quaternion is initialized to the identity quaternion (1, 0, 0, 0).
Note: in version 1.77 or earlier, the quaternion is incorrectly initialised to the zero quaternion (0, 0, 0, 0) if no value is provided. For portability you should therefore provide a value to the constructor.
conjugate
This method was added in Oolite test release 1.77.
function conjugate() : Quaternion
Return the conjugate of the quaternion (i.e. the quaternion which when multiplied by the original quaternion returns the identity quaternion). The input quaternion must be normalized.
dot
function dot(q : quaternionExpression) : Number
Returns the quaternion dot product (inner product) of the target and q
. (For two normalized quaternions, this will be 1 if they’re equal, -1 if they’re opposite and 0 if they’re perpendicular.)
multiply
function multiply(q : quaternionExpression) : Quaternion
Returns the standard quaternion product (Grassmann product) of the target and q
. This is used to concatenate rotations together.
normalize
function normalize() : Quaternion
Returns the quaternion adjusted to fulfill the normal invariant. Specifically, this divides each component by the square root of (w² + x² + y² + z²).
rotate
function rotate(a : vectorExpression, angle : Number) : Quaternion
Returns a quaternion rotated angle
radians about the axis of a
. The vector a
must be a normalized vector. A positive angle is anti-clockwise if the vector is pointing towards you.
rotateX
function rotateX(angle : Number) : Quaternion
Returns a quaternion rotated angle
radians about the x axis. A positive angle is anti-clockwise if the x axis is pointing towards you.
q.rotateX(angle)
is equivalent to q.rotate([1, 0, 0], angle)
.
rotateY
function rotateY(angle : Number) : Quaternion
Returns a quaternion rotated angle
radians about the y axis. A positive angle is anti-clockwise if the y axis is pointing towards you.
q.rotateY(angle)
is equivalent to q.rotate([0, 1, 0], angle)
.
rotateZ
function rotateZ(angle : Number) : Quaternion
Returns a quaternion rotated angle
radians about the z axis. A positive angle is anti-clockwise if the z axis is pointing towards you.
q.rotateZ(angle)
is equivalent to q.rotate([0, 0, 1], angle)
.
toArray
function toArray() : Array
Returns an array of the quaternion’s components, in the order [w, x, y, z]
. q.toArray()
is equivalent to [q.w, q.x, q.y, q.z]
.
vectorForward
function vectorForward() : Vector
Returns the forward vector from the quaternion.
To understand this, consider an entity which is aligned with the world co-ordinate system – that is, its orientation
is the identity quaternion (1, 0, 0, 0), and thus its x axis is aligned with the world x axis, its y axis is aligned with the world y axis and its z axis is aligned with the world z axis. If it is rotated by a quaternion Q, Q.vectorForward()
is the forward (z) axis after rotation. Similarly, Q.vectorUp()
is the up (y) axis after rotation, and Q.vectorRight()
is the right (x) axis after rotation.
vectorRight
function vectorRight() : Vector
Returns the right vector from the quaternion. See vectorForward()
for a definition.
vectorUp
function vectorUp() : Vector
Returns the up vector from the quaternion. See vectorForward()
for a definition.
Static Methods
random
function random() : Quaternion
Returns a random normalized quaternion.