Skip to main content
Version: v3.1.36

Rotations

Introduction

In CasualOS, Rotations are useful objects that represent 3D orientations and changes in orientation. Mathematically, CasualOS uses Quaternions to represent rotations.

Practically, CasualOS allows constructing rotations from Euler angles (X, Y, and Z angles) as well as from an arbitrary 3D axis and angle or even a sequence of rotations. When saved to tags, rotations are stored as rotation tags.

Rotation

Rotation is a class that is able to represent 2D positions and directions.

Defines a class that can represent geometric rotations.

quaternion: Quaternion

The quaternion that this rotation uses.

constructor(rotation?: (Quaternion | AxisAndAngle | FromToRotation | LookRotation | QuaternionRotation | SequenceRotation | EulerAnglesRotation)): Rotation

Creates a new rotation using the given parameters.

The first parameter is optional and is a (Quaternion | AxisAndAngle | FromToRotation | LookRotation | QuaternionRotation | SequenceRotation | EulerAnglesRotation) and is the information that should be used to construct the rotation.

Examples

Create a rotation from an axis and angle.
const rotation = new Rotation({
axis: new Vector3(0, 0, 1),
angle: Math.PI / 2
}); // 90 degree rotation around Z axis
Create a rotation from two vectors.
const rotation = new Rotation({
from: new Vector3(1, 0, 0),
to: new Vector3(0, 1, 0)
}); // Rotation that rotates (1, 0, 0) to (0, 1, 0)
Create a rotation that looks along the X axis.
const rotation = new Rotation({
direction: new Vector3(1, 0, 0),
upwards: new Vector3(0, 0, 1),
errorHandling: 'nudge'
});
Tilt this bot forwards in the home dimension.
tags.homeRotation = new Rotation({
axis: new Vector3(1, 0, 0),
angle: Math.PI / 6 // 30 degrees
});

axisAndAngle(): AxisAndAngle

Gets the axis and angle that this rotation rotates around.

combineWith(other: Rotation): Rotation

Combines this rotation with the other rotation and returns a new rotation that represents the combination of the two.

The first parameter is a Rotation and is the other rotation.

Examples

Combine two rotations together.
const first = new Rotation({
axis: new Vector3(1, 0, 0),
angle: Math.PI / 4
}); // 45 degree rotation around X axis
const second = new Rotation({
axis: new Vector3(1, 0, 0),
angle: Math.PI / 4
}); // 45 degree rotation around X axis

const third = first.combineWith(second); // 90 degree rotation around X

os.toast(third);

equals(other: Rotation): boolean

Determines if this rotation equals the other rotation.

The first parameter is a Rotation and is the rotation to check.

invert(): Rotation

Calculates the inverse rotation of this rotation and returns a new rotation with the result.

Examples

Calculate the inverse of a rotation.
const first = new Rotation({
axis: new Vector3(1, 0, 0),
angle: Math.PI / 4
}); // 45 degree rotation around X axis
const inverse = first.inverse();

const result = first.combineWith(inverse);

os.toast(result);

rotateVector2(vector: Vector2): Vector3

Rotates the given Vector2 by this quaternion and returns a new vector containing the result. Note that rotations around any other axis than (0, 0, 1) or (0, 0, -1) can produce results that contain a Z component.

The first parameter is a Vector2 and is the 2D vector that should be rotated.

Examples

Apply a rotation to a Vector2 object.
const rotation = new Rotation({
axis: new Vector3(1, 0, 0),
angle: Math.PI / 4
}); // 45 degree rotation around X axis

const point = new Vector2(1, 2);
const rotated = rotation.rotateVector2(point);
os.toast(rotated);

rotateVector3(vector: Vector3): Vector3

Rotates the given Vector3 by this quaternion and returns a new vector containing the result.

The first parameter is a Vector3 and is the 3D vector that should be rotated.

Examples

Apply a rotation to a Vector3 object.
const rotation = new Rotation({
axis: new Vector3(1, 0, 0),
angle: Math.PI / 4
}); // 45 degree rotation around X axis

const point = new Vector3(1, 2, 0);
const rotated = rotation.rotateVector3(point);
os.toast(rotated);

toString(): string

Converts this rotation to a human-readable string representation.

Examples

Get a string of a rotation.
const myRotation = new Rotation({
axis: new Vector3(1, 0, 0),
angle: Math.PI / 4
}); // 45 degree rotation around X axis
const rotationString = myRotation.toString();

os.toast('My Rotation: ' + rotationString);

static angleBetween(first: Rotation, second: Rotation): number

Determines the angle between the two given quaternions and returns the result in radians.

The first parameter is a Rotation and is the first quaternion. Must be a quaterion that represents a rotation

The second parameter is a Rotation and is the second quaternion.

static interpolate(first: Rotation, second: Rotation, amount: number): Rotation

Constructs a new rotation that is the spherical linear interpolation between the given first and second rotations. The degree that the result is interpolated is determined by the given amount parameter.

The first parameter is a Rotation and is the first rotation.

The second parameter is a Rotation and is the second rotation.

The third parameter is a number and is the amount that the resulting rotation should be interpolated between the first and second rotations. Values near 0 indicate rotations close to the first and values near 1 indicate rotations close to the second.

static quaternionFromAxisAndAngle(axisAndAngle: AxisAndAngle): Quaternion

Constructs a new Quaternion from the given axis and angle.

The first parameter is a AxisAndAngle and is the object that contains the axis and angle values.

static quaternionFromTo(fromToRotation: FromToRotation): Quaternion

Constructs a new Quaternion from the given from/to rotation. This is equivalent to calculating the cross product and angle between the two vectors and constructing an axis/angle quaternion.

The first parameter is a FromToRotation and is the object that contains the from and to values.

static quaternionLook(look: LookRotation): Quaternion

Constructs a new Quaternion from the given look rotation.

The first parameter is a LookRotation and is the object that contains the look rotation values.

Quaternion

Quaternion is a class that represents a 3D rotation by using Quaternion math.

Defines a class that represents a Quaternion. That is, a representation of a 3D rotation.

Quaternions are a mathematical representation of 3D transformations and are commonly used to calculate and apply rotations to 3D points. They work by defining a quaterion such that q = w + xi + yj + z*k, where w, x, y, and z are real numbers and i, j, and k are imaginary numbers. The basics of this is that x, y, and z define a vector that represents the rotation axis, and w defines an angle around which the rotation occurs. However, because i, j, and k are included we can keep x, y, and z from incorrectly interacting with each other and so avoid common pitfalls like Gimbal lock.

One little known feature of quaternions is that they can also represent reflections and also scale. This is because there are two different ways to apply a quaternion to a 3D point:

  • quaterion * point * inverse(quaterion)

This formula rotates and scales the point quaternion. The rotation occurs around the axis specified by the quaternion X, Y, and Z values. Additionally, the point will be scaled by the length of the quaternion. (i.e. sqrt( x^2 + y^2 + z^2 + w^2 )) This is why quaternions that are used to represent only rotations must be normalized.

  • quaternion * point * quaternion

This formula reflects scales the point by the quaternion. The reflection occurs across the axis specified by the quaternion X, Y, and Z values. Additionally, the point will be scaled by the length of the quaternion. (i.e. sqrt( x^2 + y^2 + z^2 + w^2 ))

w: number

The W value of the quaternion.

x: number

The X value of the quaternion.

y: number

The Y value of the quaternion.

z: number

The Z value of the quaternion.

constructor(x: number, y: number, z: number, w: number): Quaternion

Creates a new Quaternion with the given values.

The first parameter is a number and is the X value.

The second parameter is a number and is the Y value.

The third parameter is a number and is the Z value.

The fourth parameter is a number and is the W value.

equals(other: Quaternion): boolean

Determines if this quaternion equals the other quaternion.

The first parameter is a Quaternion and is the other quaternion to apply.

invert(): Quaternion

Calculates the conjugate of this quaternion and returns the result. The conjugate (or inverse) of a quaternion is similar to negating a number. When you multiply a quaternion by its conjugate, the result is the identity quaternion.

length(): number

Gets the length of this vector. That is, the pathagorean theorem applied to X, Y, Z, and W.

multiply(other: Quaternion): Quaternion

Multiplies this quaternion by the other quaternion and returns the result. In quaternion math, multiplication can be used to combine quaternions together, however unlike regular multiplication quaternion multiplication is order dependent.

Which frame of reference you want to use depends on which order you use. For example, q2.multiply(q1) starts with the identity, applies q1 to it, and then applies q2 to that. Whereas, q1.multiply(q2) starts with the identity, applies q2 to it, and then applies q1 to that.

The first parameter is a Quaternion and is the other quaternion.

normalize(): Quaternion

Calculates the normalized version of this quaternion and returns it. A normalized quaternion is a quaternion whose length equals 1.

Normalizing a quaternion preserves its rotation/reflection while making the length (i.e. scale) of it 1.

squareLength(): number

Calculates the square length of this quaternion and returns the result. This is equivalent to length^2, but it is faster to calculate than length because it doesn't require calculating a square root.

toString(): string

AxisAndAngle

AxisAndAngle is a type that represents a 3D rotation around an arbitrary 3D axis.

It should be an object that contains the following properties:

Defines an interface that represents an Axis and Angle pair.

angle: number

The number of radians that should be rotated around the axis.

axis: Vector3

The axis about which the angle should rotate around.

FromToRotation

FromToRotation is a type that represents a 3D rotation that rotates one vector into another vector.

It should be an object that contains the following properties:

Defines an interface that represents a from/to rotation. That is, a rotation that is able to rotate a vector from the given vector direction to the given vector direction.

from: Vector3

The direction that the rotation should rotate from.

to: Vector3

The direction that the rotation should rotate to.

SequenceRotation

SequenceRotation is a type that represents a 3D rotation by combining several rotations together.

It should be an object that contains the following properties:

Defines an interface that represents a sequence of rotations.

sequence: Rotation[]

The sequence of successive rotations.

EulerAnglesRotation

EulerAnglesRotation is a type that represents a 3D rotation using separate X, Y, and Z values.

It should be an object that contains the following properties:

const eulerAnglesRotation: {
euler: {
/**
* The amount to rotate around the X axis.
*/
x: number;

/**
* The amount to rotate around the Y axis.
*/
y: number;

/**
* The amount to rotate around the Z axis.
*/
z: number;

/**
* The order that the rotations should be applied in.
* Defaults to XYZ
*/
order?: string;

/**
* Whether the euler angles are extrinsic.
* Defaults to false.
*/
extrinsic?: boolean;
};
}

QuaternionRotation

QuaternionRotation is a type that represents a 3D rotation by using a Quaternion.

It should be an object that contains the following properties:

export interface QuaternionRotation {
quaternion: { x: number; y: number; z: number; w: number };
}

LookRotation

LookRotation is a type that represents a 3D rotation by using a direction and upwards vector. The resulting rotations are able to orient a bot such that the rear bot face is looking along the direction and the top bot face is looking in the same direction as the upwards vector.

It should be an object that contains the following properties:

export interface LookRotation {
/**
* The direction that (0, 1, 0) should be pointing along after the rotation is applied.
*/
direction: Vector3;

/**
* The direction that the upward axis should be pointing along after the rotation is applied.
* If the direction and upwards vectors are not perpendicular, then the direction will be prioritized and the angle between
* upwards and the resulting upwards vector will be minimized.
*
* If direction and upwards are perpendicular, then applying the rotation to (0, 0, 1) will give the upwards vector.
*/
upwards: Vector3;

/**
* How errors with the direction and upwards vectors should be handled.
* If the direction and upwards vectors are parallel or perpendicular, then it is not possible to create a rotation
* that looks along the direction and uses the upwards vector. The upwards vector is essentially useless in this scenario
* and as a result there are an infinite number of possible valid rotations that look along direction vector.
*
* This parameter provides two ways to handle this situation:
*
* - "error" indicates that an error should be thrown when this situation arises.
* - "nudge" indicates that the direction vector should be nudged by a miniscule amount in an arbitrary direction.
* This causes the upwards and direction vectors to no longer be parallel, but it can also cause rotation bugs when the direction and upwards are the same.
*/
errorHandling: 'error' | 'nudge';
}