diff --git a/eslint.config.js b/eslint.config.js index 9fa51b227..6aa12ab57 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -61,7 +61,8 @@ export default tseslint.config( quotes: [2, 'single'], 'no-proto': 2, 'linebreak-style': 2, - 'key-spacing': [2, {afterColon: true}] + 'key-spacing': [2, {afterColon: true}], + 'eol-last': ['error', 'always'], }, files: ['**/*.{js,jsx,ts,tsx,cjs}'], } diff --git a/src/math/Pose.js b/src/math/Pose.ts similarity index 52% rename from src/math/Pose.js rename to src/math/Pose.ts index adb84eaec..5ab924169 100644 --- a/src/math/Pose.js +++ b/src/math/Pose.ts @@ -2,67 +2,78 @@ * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ +import Vector3, { type IVector3 } from './Vector3.js'; +import Quaternion, { type IQuaternion } from './Quaternion.js'; +import { type ITransform } from './Transform.js'; +import { PartialNullable } from '../types/interface-types.js'; -import Vector3 from './Vector3.js'; -import Quaternion from './Quaternion.js'; -import Transform from './Transform.js'; +export interface IPose { + /** + * The ROSLIB.Vector3 describing the position. + */ + position: IVector3; + /** + * The ROSLIB.Quaternion describing the orientation. + */ + orientation: IQuaternion; +} /** * A Pose in 3D space. Values are copied into this object. */ -export default class Pose { - /** - * @param {Object} [options] - * @param {Vector3} [options.position] - The ROSLIB.Vector3 describing the position. - * @param {Quaternion} [options.orientation] - The ROSLIB.Quaternion describing the orientation. - */ - constructor(options) { - options = options || {}; - // copy the values into this object if they exist - options = options || {}; - this.position = new Vector3(options.position); - this.orientation = new Quaternion(options.orientation); +export default class Pose implements IPose { + + position: Vector3; + orientation: Quaternion; + + constructor(options?: PartialNullable) { + this.position = new Vector3(options?.position); + this.orientation = new Quaternion(options?.orientation); } + /** * Apply a transform against this pose. * - * @param {Transform} tf - The transform to be applied. + * @param {ITransform} tf - The transform to be applied. */ - applyTransform(tf) { + applyTransform(tf: ITransform) { this.position.multiplyQuaternion(tf.rotation); this.position.add(tf.translation); - var tmp = tf.rotation.clone(); + const tmp = new Quaternion(tf.rotation); tmp.multiply(this.orientation); this.orientation = tmp; } + /** * Clone a copy of this pose. * * @returns {Pose} The cloned pose. */ - clone() { + clone(): Pose { return new Pose(this); } + /** * Multiply this pose with another pose without altering this pose. * * @returns {Pose} The result of the multiplication. */ - multiply(pose) { - var p = pose.clone(); + multiply(pose: Pose): Pose { + const p = pose.clone(); p.applyTransform({ rotation: this.orientation, translation: this.position }); return p; } + /** * Compute the inverse of this pose. * * @returns {Pose} The inverse of the pose. */ - getInverse() { - var inverse = this.clone(); + getInverse(): Pose { + const inverse = this.clone(); inverse.orientation.invert(); inverse.position.multiplyQuaternion(inverse.orientation); inverse.position.x *= -1; diff --git a/src/math/Quaternion.js b/src/math/Quaternion.ts similarity index 52% rename from src/math/Quaternion.js rename to src/math/Quaternion.ts index c43919dfb..ed161dcd5 100644 --- a/src/math/Quaternion.js +++ b/src/math/Quaternion.ts @@ -2,46 +2,69 @@ * @fileOverview * @author David Gossow - dgossow@willowgarage.com */ +import { type PartialNullable } from '../types/interface-types.js'; + +export interface IQuaternion { + /** + * The x value. + */ + x: number; + + /** + * The y value. + */ + y: number; + + /** + * The z value. + */ + z: number; + + /** + * The w value. + */ + w: number; +} /** * A Quaternion. */ -export default class Quaternion { - /** - * @param {Object} [options] - * @param {number|null} [options.x=0] - The x value. - * @param {number|null} [options.y=0] - The y value. - * @param {number|null} [options.z=0] - The z value. - * @param {number|null} [options.w=1] - The w value. - */ - constructor(options) { - options = options || {}; - this.x = options.x || 0; - this.y = options.y || 0; - this.z = options.z || 0; - this.w = typeof options.w === 'number' ? options.w : 1; +export default class Quaternion implements IQuaternion { + x: number; + y: number; + z: number; + w: number; + + constructor(options?: PartialNullable | null) { + this.x = options?.x ?? 0; + this.y = options?.y ?? 0; + this.z = options?.z ?? 0; + this.w = typeof options?.w === 'number' ? options.w : 1; } + /** * Perform a conjugation on this quaternion. */ - conjugate() { + conjugate(): void { this.x *= -1; this.y *= -1; this.z *= -1; } + /** * Return the norm of this quaternion. */ - norm() { + norm(): number { return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); } + /** * Perform a normalization on this quaternion. */ - normalize() { - var l = Math.sqrt( + normalize(): void { + let l = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); if (l === 0) { @@ -67,24 +90,25 @@ export default class Quaternion { /** * Set the values of this quaternion to the product of itself and the given quaternion. * - * @param {Quaternion} q - The quaternion to multiply with. + * @param {IQuaternion} q - The quaternion to multiply with. */ - multiply(q) { - var newX = this.x * q.w + this.y * q.z - this.z * q.y + this.w * q.x; - var newY = -this.x * q.z + this.y * q.w + this.z * q.x + this.w * q.y; - var newZ = this.x * q.y - this.y * q.x + this.z * q.w + this.w * q.z; - var newW = -this.x * q.x - this.y * q.y - this.z * q.z + this.w * q.w; + multiply(q: IQuaternion): void { + const newX = this.x * q.w + this.y * q.z - this.z * q.y + this.w * q.x; + const newY = -this.x * q.z + this.y * q.w + this.z * q.x + this.w * q.y; + const newZ = this.x * q.y - this.y * q.x + this.z * q.w + this.w * q.z; + const newW = -this.x * q.x - this.y * q.y - this.z * q.z + this.w * q.w; this.x = newX; this.y = newY; this.z = newZ; this.w = newW; } + /** * Clone a copy of this quaternion. * * @returns {Quaternion} The cloned quaternion. */ - clone() { + clone(): Quaternion { return new Quaternion(this); } } diff --git a/src/math/Transform.js b/src/math/Transform.js deleted file mode 100644 index 4139f63aa..000000000 --- a/src/math/Transform.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @fileOverview - * @author David Gossow - dgossow@willowgarage.com - */ - -import Vector3 from './Vector3.js'; -import Quaternion from './Quaternion.js'; - -/** - * A Transform in 3-space. Values are copied into this object. - */ -export default class Transform { - /** - * @param {Object} options - * @param {Vector3} options.translation - The ROSLIB.Vector3 describing the translation. - * @param {Quaternion} options.rotation - The ROSLIB.Quaternion describing the rotation. - */ - constructor(options) { - // Copy the values into this object if they exist - this.translation = new Vector3(options.translation); - this.rotation = new Quaternion(options.rotation); - } - /** - * Clone a copy of this transform. - * - * @returns {Transform} The cloned transform. - */ - clone() { - return new Transform(this); - } -} diff --git a/src/math/Transform.ts b/src/math/Transform.ts new file mode 100644 index 000000000..176423edf --- /dev/null +++ b/src/math/Transform.ts @@ -0,0 +1,42 @@ +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +import Vector3, { type IVector3 } from './Vector3.js'; +import Quaternion, { type IQuaternion } from './Quaternion.js'; + +export interface ITransform { + /** + * The ROSLIB.Vector3 describing the translation. + */ + translation: IVector3; + /** + * The ROSLIB.Quaternion describing the rotation. + */ + rotation: IQuaternion; +} + +/** + * A Transform in 3-space. Values are copied into this object. + */ +export default class Transform implements ITransform { + + translation: Vector3; + rotation: Quaternion; + + constructor(options: ITransform) { + // Copy the values into this object if they exist + this.translation = new Vector3(options.translation); + this.rotation = new Quaternion(options.rotation); + } + + /** + * Clone a copy of this transform. + * + * @returns {Transform} The cloned transform. + */ + clone(): Transform { + return new Transform(this); + } +} diff --git a/src/math/Vector3.js b/src/math/Vector3.ts similarity index 53% rename from src/math/Vector3.js rename to src/math/Vector3.ts index 3d9f933e2..f1d580903 100644 --- a/src/math/Vector3.js +++ b/src/math/Vector3.ts @@ -3,64 +3,81 @@ * @author David Gossow - dgossow@willowgarage.com */ -import Quaternion from './Quaternion.js'; +import { type IQuaternion } from './Quaternion.js'; +import { type PartialNullable } from '../types/interface-types.js'; + +export interface IVector3 { + /** + * The x value. + */ + x: number; + /** + * The y value. + */ + y: number; + /** + * The z value. + */ + z: number; +} /** * A 3D vector. */ -export default class Vector3 { - /** - * @param {Object} [options] - * @param {number} [options.x=0] - The x value. - * @param {number} [options.y=0] - The y value. - * @param {number} [options.z=0] - The z value. - */ - constructor(options) { - options = options || {}; - this.x = options.x || 0; - this.y = options.y || 0; - this.z = options.z || 0; +export default class Vector3 implements IVector3 { + x: number; + y: number; + z: number; + + constructor(options?: PartialNullable | null) { + this.x = options?.x ?? 0; + this.y = options?.y ?? 0; + this.z = options?.z ?? 0; } + /** * Set the values of this vector to the sum of itself and the given vector. * * @param {Vector3} v - The vector to add with. */ - add(v) { + add(v: IVector3): void { this.x += v.x; this.y += v.y; this.z += v.z; } + /** * Set the values of this vector to the difference of itself and the given vector. * * @param {Vector3} v - The vector to subtract with. */ - subtract(v) { + subtract(v: IVector3): void { this.x -= v.x; this.y -= v.y; this.z -= v.z; } + /** * Multiply the given Quaternion with this vector. * * @param {Quaternion} q - The quaternion to multiply with. */ - multiplyQuaternion(q) { - var ix = q.w * this.x + q.y * this.z - q.z * this.y; - var iy = q.w * this.y + q.z * this.x - q.x * this.z; - var iz = q.w * this.z + q.x * this.y - q.y * this.x; - var iw = -q.x * this.x - q.y * this.y - q.z * this.z; + multiplyQuaternion(q: IQuaternion) { + const ix = q.w * this.x + q.y * this.z - q.z * this.y; + const iy = q.w * this.y + q.z * this.x - q.x * this.z; + const iz = q.w * this.z + q.x * this.y - q.y * this.x; + const iw = -q.x * this.x - q.y * this.y - q.z * this.z; this.x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y; this.y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z; this.z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x; } + /** * Clone a copy of this vector. * * @returns {Vector3} The cloned vector. */ - clone() { + clone(): Vector3 { return new Vector3(this); } } diff --git a/src/math/index.ts b/src/math/index.ts index 8260ddf71..6192483fa 100644 --- a/src/math/index.ts +++ b/src/math/index.ts @@ -1,4 +1,4 @@ -export { default as Pose } from './Pose.js'; -export { default as Quaternion } from './Quaternion.js'; -export { default as Transform } from './Transform.js'; -export { default as Vector3 } from './Vector3.js'; +export { default as Pose, type IPose } from './Pose.js'; +export { default as Quaternion, type IQuaternion } from './Quaternion.js'; +export { default as Transform, type ITransform } from './Transform.js'; +export { default as Vector3, type IVector3 } from './Vector3.js'; diff --git a/src/types/interface-types.ts b/src/types/interface-types.ts new file mode 100644 index 000000000..1fbe2a89c --- /dev/null +++ b/src/types/interface-types.ts @@ -0,0 +1,16 @@ +/** + * Represents a type that can either be a value of type `T` or `undefined`. + */ +export type Optional = T | undefined; + +/** + * Represents a type that can either be a value of type `T` or `null`. + */ +export type Nullable = T | null; + +/** + * Represents an object type where all properties are optional, and included properties can be null or undefined. + */ +export type PartialNullable = { + [P in keyof T]?: Nullable; +};