Functions
3D Vectors
Functions to construct 3D vectors v::SVector{3,F}.
Modia3D.Frames.ZeroVector3D — FunctionModia3D.ZeroVector3D(::Type{F}) where F = SVector{3,F}(0, 0, 0)Constant of a SVector{3,Float64} where all elements are zero
Modia3D.Frames.axisValue — Functionvec = Modia3D.axisValue(axis, value::F) where F
vec = Modia3D.axisValue(axis, positive, value::F) where FReturn vec::SVector{3,F} where all elements are zero with exception of vec[axis] = value or vec[axis] = positive ? value : -value.
Rotation Matrices
Functions to construct rotation matrices R::SMatrix{3,3,F,9} rotating a coordinate-system/frame 1 into a coordinate-system/frame 2.
| Function | Description |
|---|---|
Modia3D.NullRotation(::Type{F}) | No rotation from frame 1 to frame 2 |
Modia3D.assertRotationMatrix(R) | Assert that R is a rotation matrix |
Modia3D.rot1(angle) | Rotate around angle along x-axis |
Modia3D.rot2(angle) | Rotate around angle along y-axis |
Modia3D.rot3(angle) | Rotate around angle along z-axis |
Modia3D.rot123(angle1, angle2, angle3) | Rotate around angles along x,y,z-axes |
Modia3D.rot123(angles) | Rotate around angles along x,y,z-axes |
Modia3D.rotAxis(axis,angle) | Rotate around angle along axis (= 1,2,3) |
Modia3D.rotAxis(axis,positive,angle) | Rotate around angle if positive, else -angle |
Modia3D.rot_e(e, angle) | Rotate around angle along unit vector e |
Modia3D.rot_nxy(nx, ny) | nx/ny are in x/y-direction of frame 2 |
Modia3D.rot_nxz(nx, nz) | nx/nz are in x/z-direction of frame 2 |
Modia3D.from_q(q) | Return rotation matrix from quaternion q |
Examples
using Modia3D
# R1,R2,R3 are the same RotationMatrices
R1 = Modia3D.rot1(pi/2)
R2 = Modia3D.rot1(90u"°")
R3 = Modia3D.rot_e([1,0,0], pi/2)Modia3D.Frames.NullRotation — FunctionR = Modia3D.MullRotation(::Type{F}) where FReturn rotation matrix R::SMatrix{3,3,F,9} that defines no rotation from frame 1 to frame 2.
Modia3D.Frames.assertRotationMatrix — FunctionModia3D.assertRotationMatrix(R::AbstractMatrix)Assert that matrix R has the properties of a rotation matrix (is 3x3 and R'*R - eye(3) = zeros(3,3))
Modia3D.Frames.rot1 — FunctionR = Modia3D.rot1(angle)Return rotation matrix R that rotates with angle angle along the x-axis of frame 1. angle can be provided in radian or in degree, e.g. using Unitful; Modia3D.rot1(90u"°").
Modia3D.rot1(angle,v::AbstractVector)Return in principal Modia3D.rot1(angle)*v, but compute this efficiently by taking the zeros in rot1(..) into account. angle can be provided in radian or in degree, e.g. using Unitful; Modia3D.rot1(90u"°", v).
Modia3D.Frames.rot2 — FunctionR = Modia3D.rot2(angle)Return rotation matrix R that rotates with angle angle along the y-axis of frame 1. angle can be provided in radian or in degree, e.g. using Unitful; Modia3D.rot2(90u"°").
Modia3D.rot2(angle,v::AbstractVector)Return in principal Modia3D.rot2(angle)*v, but compute this efficiently by taking the zeros in rot2(..) into account. angle can be provided in radian or in degree, e.g. using Unitful; Modia3D.rot2(90u"°", v).
Modia3D.Frames.rot3 — FunctionR = Modia3D.rot3(angle)Return rotation matrix R that rotates with angle angle along the z-axis of frame 1. angle can be provided in radian or in degree, e.g. using Unitful; Modia3D.rot3(90u"°").
Modia3D.rot3(angle,v::AbstractVector)Return in principal Modia3D.rot3(angle)*v, but compute this efficiently by taking the zeros in rot3(..) into account. angle can be provided in radian or in degree, e.g. using Unitful; Modia3D.rot3(90u"°", v).
Modia3D.Frames.rot123 — FunctionR = Modia3D.rot123(angle1, angle2, angle3)
R = Modia3D.rot123(angles)Return rotation matrix R by rotating with angle1 along the x-axis of frame 1, then with angle2 along the y-axis of this frame and then with angle3 along the z-axis of this frame. The angles can be optionally provided in form of a vector angles = [angle1, angle2, angle3].
Modia3D.Frames.rotAxis — FunctionR = Modia3D.rotAxis(axis, angle)
R = Modia3D.rotAxis(axis, positive, angle)Return rotation matrix R that rotates with angle angle along axis axis (= 1, 2 or 3), or with angle if positive=true and otherwise with -angle. angle can be provided in radian or in degree, e.g. using Unitful; Modia3D.rotAxis(2, 90u"°").
Modia3D.Frames.rot_e — FunctionR = Modia3D.rot_e(e, angle)Return rotation matrix that rotates frame1 around angle along unit axis e arriving at frame2. This function assumes that norm(e) == 1.
Modia3D.Frames.rot_nxy — FunctionR = Modia3D.rot_nxy(nx, ny)It is assumed that the two input vectors nx and ny are resolved in frame 1 and are directed along the x and y axis of frame 2. The function returns the rotation matrix R to rotate from frame 1 to frame 2.
The function is robust in the sense that it returns always a rotation matrix R, even if ny is not orthogonal to nx or if one or both vectors have zero length. This is performed in the following way: If nx and ny are not orthogonal to each other, first a unit vector ey is determined that is orthogonal to nx and is lying in the plane spanned by nx and ny. If nx and ny are parallel or nearly parallel to each other or ny is a vector with zero or nearly zero length, a vector ey is selected arbitrarily such that ex and ey are orthogonal to each other. If both nx and ny are vectors with zero or nearly zero length, an arbitrary rotation matrix is returned.
Example
using Unitful
import Modia3D
R1 = Modia3D.rot1(90u"°")
R2 = Modia3D.rot_nxy([1 , 0, 0], [0 , 0, 1 ])
R3 = Modia3D.rot_nxy([0.9, 0, 0], [1.1, 0, 1.1])
isapprox(R1,R2) # returns true
isapprox(R1,R3) # returns trueModia3D.Frames.rot_nxz — FunctionR = Modia3D.rot_nxz(nx, nz)It is assumed that the two input vectors nx and nz are resolved in frame 1 and are directed along the x and y axis of frame 2. The function returns the rotation matrix R to rotate from frame 1 to frame 2.
The function is robust in the sense that it returns always a rotation matrix R, even if nx is not orthogonal to nz or if one or both vectors have zero length. This is performed in the following way: If nx and nz are not orthogonal to each other, first a unit vector ex is determined that is orthogonal to nz and is lying in the plane spanned by nx and nz. If nx and nz are parallel or nearly parallel to each other or nx is a vector with zero or nearly zero length, a vector ex is selected arbitrarily such that ex and ez are orthogonal to each other. If both nx and nz are vectors with zero or nearly zero length, an arbitrary rotation matrix is returned.
Example
using Unitful
import Modia3D
R1 = Modia3D.rot3(90u"°")
R2 = Modia3D.rot_nxz([0, 1 , 0 ], [0, 0, 1 ])
R3 = Modia3D.rot_nxz([0, 1.1, 1.1], [0, 0, 0.9])
isapprox(R1,R2) # returns true
isapprox(R1,R3) # returns trueModia3D.Frames.from_q — FunctionR = Modia3D.from_q(q)Return rotation matrix R::SMatrix{3,3,F,9} from quaternions q::SVector{4,F}.
Quaternions
Functions to construct quaternions q::SVector{4,F} rotating a coordinate-system/frame 1 into a coordinate-system/frame 2.
| Function | Description |
|---|---|
Modia3D.NullQuaternion(::Type{F}) | No rotation from frame 1 to frame 2 |
Modia3D.assertQuaternion(q) | Assert that q is a quaternion |
Modia3D.qrot1(angle) | Rotate around angle along x-axis |
Modia3D.qrot2(angle) | Rotate around angle along y-axis |
Modia3D.qrot3(angle) | Rotate around angle along z-axis |
Modia3D.qrot123(angle1, angle2, angle3) | Rotate around angles along x,y,z-axes |
Modia3D.qrot_e(e, angle) | Rotate around angle along unit vector e |
Modia3D.qrot_nxy(nx, ny) | nx/ny are in x/y-direction of frame 2 |
Modia3D.qrot_nxz(nx, nz) | nx/nz are in x/z-direction of frame 2 |
Modia3D.from_R(R) | Return q from rotation matrix R |
Modia3D.Frames.NullQuaternion — Functionconst Modia3D.NullQuaternion(F) = SVector{4,F}(0.0, 0.0, 0.0, 1.0)Constant quaternion vector of a null rotation (= no rotation from frame 1 to frame 2)
Modia3D.Frames.assertQuaternion — FunctionModia3D.assertQuaternion(q::AbstractVector)Assert that vector q has the properties of a quaternion vector (has 4 elements, norm(q) = 1)
Modia3D.Frames.qrot1 — Functionq = Modia3D.qrot1(angle; q_guess = NullQuaternion(F))Return quaternion q that rotates with angle angle along the x-axis of frame 1.
From the two possible solutions q the one is returned that is closer to q_guess (note, q and -q define the same rotation).
Modia3D.Frames.qrot2 — Functionq = Modia3D.qrot2(angle; q_guess = NullQuaternion(F))Return quaternion q that rotates with angle angle along the y-axis of frame 1.
From the two possible solutions q the one is returned that is closer to q_guess (note, q and -q define the same rotation).
Modia3D.Frames.qrot3 — Functionq = Modia3D.qrot3(angle; q_guess = NullQuaternion(F))Return quaternion q that rotates with angle angle along the z-axis of frame 1.
From the two possible solutions q the one is returned that is closer to q_guess (note, q and -q define the same rotation).
Modia3D.Frames.qrot123 — Functionq = Modia3D.qrot123(angle1, angle2, angle3)Return quaternion q by rotating with angle1 along the x-axis of frame 1, then with angle2 along the y-axis of this frame and then with angle3 along the z-axis of this frame.
From the two possible solutions q the one is returned that is closer to q_guess (note, q and -q define the same rotation).
Modia3D.Frames.qrot_e — Functionq = Modia3D.qrot_e(e, angle; q_guess = NullQuaternion(F))Return quaternion q that rotates with angle angle along unit axis e. This function assumes that norm(e) == 1.
From the two possible solutions q the one is returned that is closer to q_guess (note, q and -q define the same rotation).
Modia3D.Frames.qrot_nxy — Functionq = Modia3D.qrot_nxy(nx, ny)It is assumed that the two input vectors nx and ny are resolved in frame 1 and are directed along the x and y axis of frame 2. The function returns the quaternion q to rotate from frame 1 to frame 2.
The function is robust in the sense that it returns always a quaternion q, even if ny is not orthogonal to nx or if one or both vectors have zero length. This is performed in the following way: If nx and ny are not orthogonal to each other, first a unit vector ey is determined that is orthogonal to nx and is lying in the plane spanned by nx and ny. If nx and ny are parallel or nearly parallel to each other or ny is a vector with zero or nearly zero length, a vector ey is selected arbitrarily such that ex and ey are orthogonal to each other. If both nx and ny are vectors with zero or nearly zero length, an arbitrary quaternion q is returned.
Example
using Unitful
import Modia3D
q1 = Modia3D.qrot1(90u"°")
q2 = Modia3D.qrot_nxy([1 , 0, 0], [0 , 0, 1 ])
q3 = Modia3D.qrot_nxy([0.9, 0, 0], [1.1, 0, 1.1])
isapprox(q1,q2) # returns true
isapprox(q1,q3) # returns trueModia3D.Frames.qrot_nxz — Functionq = Modia3D.qrot_nxz(nx, nz)It is assumed that the two input vectors nx and nz are resolved in frame 1 and are directed along the x and z axis of frame 2. The function returns the quaternion q to rotate from frame 1 to frame 2.
The function is robust in the sense that it returns always a quaternion q, even if nx is not orthogonal to nz or if one or both vectors have zero length. This is performed in the following way: If nx and nz are not orthogonal to each other, first a unit vector ex is determined that is orthogonal to nz and is lying in the plane spanned by nx and nz. If nx and nz are parallel or nearly parallel to each other or nx is a vector with zero or nearly zero length, a vector ex is selected arbitrarily such that ex and ez are orthogonal to each other. If both nx and nz are vectors with zero or nearly zero length, an arbitrary quaternion q is returned.
Example
using Unitful
import Modia3D
q1 = Modia3D.qrot3(90u"°")
q2 = Modia3D.qrot_nxz([0, 1 , 0 ], [0, 0, 1 ])
q3 = Modia3D.qrot_nxz([0, 1.1, 1.1], [0, 0, 0.9])
isapprox(q1,q2) # returns true
isapprox(q1,q3) # returns trueModia3D.Frames.from_R — Functionq = Modia3D.from_R(R; q_guess = NullQuaternion(F))Return quaternion q::SVector{4,F} from rotation matrix R::SMatrix{3,3,F,9}.
From the two possible solutions q the one is returned that is closer to q_guess (note, q and -q define the same rotation).
Frame Transformations
Functions to transform vectors, rotation matrices, quaternions between coordinate systems and functions to determine properties from coordinate system transformations.
| Function | Description |
|---|---|
Modia3D.resolve1(rot, v2) | Transform vector v from frame 2 to frame 1 |
Modia3D.resolve2(rot, v1) | Transform vector v from frame 1 to frame 2 |
Modia3D.absoluteRotation(rot01, rot12) | Return rotation 0->2 from rot. 0->1 and 1->2 |
Modia3D.relativeRotation(rot01, rot02) | Return rotation 1->2 from rot. 0->1 and 0->2 |
Modia3D.inverseRotation(rot01) | Return rotation 1->0 from rot, 0->1 |
Modia3D.planarRotationAngle(e,v1,v2) | Return angle of planar rotation along e |
Modia3D.eAxis(axis) | Return unit vector e in direction of axis |
Modia3D.skew(v) | Return skew-symmetric matrix of vector v |
Modia3D.Frames.resolve1 — Functionv1 = Modia3D.resolve1(R, v2)
v1 = Modia3D.resolve1(q, v2)
v1 = Modia3D.resolve1(rotation, v2; rotationXYZ=true)Transform vector v2::AbstractVector (vector resolved in frame 2) to vector v1::SVector{3,F} (vector resolved in frame 1) given
- Rotation matrix
R::SMatrix{3,3,F,9}(rotate frame 1 into frame 2) or - Quaternion vector
q::SVector{4,F}(rotate frame 1 into frame 2) or - Angles vector
rotation::AbstractVector(rotationXYZ=true: rotate around X with rotation[1], around Y with rotation[2], around Z with rotation[3]; rotationXYZ=false: rotate around X with rotation[1], around Z with rotation[2], around Y with rotation[3]).
Modia3D.Frames.resolve2 — Functionv2 = Modia3D.resolve2(R, v1)
v2 = Modia3D.resolve2(q, v1)
v2 = Modia3D.resolve2(rotation, v1; rotationXYZ=true)Transform vector v1::AbstractVector (vector resolved in frame 1) to vector v2::SVector{3,F} (vector resolved in frame 2) given
- Rotation matrix
R::SMatrix{3,3,F,9}(rotate frame 1 into frame 2) or - Quaternion vector
q::SVector{4,F}(rotate frame 1 into frame 2) or - Angles vector
rotation::AbstractVector(rotationXYZ=true: rotate around X with rotation[1], around Y with rotation[2], around Z with rotation[3]; rotationXYZ=false: rotate around X with rotation[1], around Z with rotation[2], around Y with rotation[3]).
Modia3D.Frames.absoluteRotation — Function R2 = Modia3D.absoluteRotation(R1, R_rel)
q2 = Modia3D.absoluteRotation(q1, q_rel)Return rotation matrix R2 or quaternion q2 defining the rotation from frame 0 to frame 2 from rotation matrix R1 or quaternion q1that define the rotation from frame 0 to frame 1 and the relative rotation matrix R_rel or the relative quaternion q_rel that define the rotation from frame 1 to frame 2.
Modia3D.Frames.relativeRotation — Function R_rel = Modia3D.relativeRotation(R1, R2)
q_rel = Modia3D.relativeRotation(q1, q2)Return relative rotation matrix R_rel or relative quaternion q_rel defining the rotation from frame 1 to frame 2 from absolute rotation matrix R1 or absolute quaternion q1 that define the rotation from frame 0 to frame 1 and the absolute rotation matrix R2 or the absolute quaternion q2 that define the rotation from frame 0 to frame 2.
Modia3D.Frames.inverseRotation — Function R_inv = Modia3D.inverseRotation(R)
q_inv = Modia3D.inverseRotation(q)Return inverse rotation matrix R_inv or inverse quaternion q_inv defining the rotation from frame 1 to frame 0 from rotation matrix R or quaternion q that define the rotation from frame 0 to frame 1.
Modia3D.Frames.planarRotationAngle — Functionangle = planarRotationAngle(e, v1, v2; angle_guess = 0.0)Return angle of a planar rotation, given the normalized axis of rotation to rotate frame 1 around e into frame 2 (norm(e) == 1 required), and the representations of a vector in frame 1 (v1) and frame 2 (v2). Hereby, it is required that v1 is not parallel to e. The returned angle is in the range -pi <= angle - angle_guess <= pi (from the infinite many solutions, the one is returned that is closest to angle_guess).
Example
import Modia3D
using Unitful
angle1 = 45u"°"
e = normalize([1.0, 1.0, 1.0])
R = Modia3D.rot_e(e, angle1)
v1 = [1.0, 2.0, 3.0]
v2 = Modia3D.resolve2(R, v1)
angle2 = planarRotationAngle(e, v1, v2)
isapprox(angle1, angle2)angle = planarRotationAngle(frame1, frame2)Under the assumption that the z-axes of frame1 and frame2 coincide, return the angle between the x-axis of frame1 and the position vector from frame1 to frame2.
Modia3D.Frames.eAxis — Functione = eAxis(::Type{F}, axis::Int)Return unit vector e::SVector{3,F} in direction of axis axis (axis = 1,2,3 or -1,-2-,3).
Example
import Modia3D
e1 = ModiMath.eAxis(1) # e1 = SVector{3,F}(1.0, 0.0, 0.0)
e2 = ModiMath.eAxis(-2) # d2 = SVector{3,F}(0.0, -1.0, 0.0)Modia3D.Frames.skew — FunctionM = Modia3D.skew(e::SVector{3,F}) where F
M = Modia3D.skew(e::Vector{F}) where FReturn the skew symmetric matrix M of vector e (length(e) = 3) with
M = @SMatrix [ F(0.0) -e[3] e[2];
e[3] F(0.0) -e[1];
-e[2] e[1] F(0.0) ]Frame Interpolations
Given a set of coordinate-systems/frames by a vector r of position vectors (to their origins) and and an optional vector q of Quaternions (of their absolute orientations), then the following functions interpolate linearly in these frames:
| Function | Description |
|---|---|
Modia3D.Path(r,q) | Return path defined by a vector of frames |
Modia3D.t_pathEnd(path) | Return path parameter t_end of last frame |
Modia3D.interpolate(path,t) | Return (rt,qt) of Path at path parameter t |
Modia3D.interpolate_r(path,t) | Return rt of Path at path parameter t |
Modia3D.Frames.Path — Typepath = Modia3D.Path(r::Vector{SVector{3,Float64}},
q::Vector{SVector{4,Float64}} = NullQuaternion(Float64);
v = ones(length(r)))Return an instance of a new Path object. The Path object consists of n frames defined by the position vectors of their origins (r[i] for frame i) and optionally of their absolute rotation quaternions (q[i] for frame i) describing the rotation from the world frame to the respective frame.
A path parameter t is defined in the following way on these frames:
t[1] = 0.0.t[i] = t[i-1] + pathLength_i/(v[i]+v[i-1])/2if the origins of framesi-1andido not coincide.t[i] = t[i-1] + pathAngle_i/(v[i]+v[i-1])/2if the origins of framesi-1andido coincide.
Hereby pathLength_i is the distance between the origins of frames i-1 and i in [m] and pathAngle_i is the planar rotation angle between frames i-1 and i in [rad].
If v[i] is the desired velocity or angular velocity at frame i, then path parameter t is approximately the time to move along the path. The time instant t_end of the last frame can be inquired with Modia3D.t_pathEnd(path). For example, if a simulation shall be performed in such a way that the simulation should start with the first frame and end at stopTime at the last frame, then the path parameter should be selected as t = time*t_end/stopTime.
Given the actual path parameter, typically 0 <= t <= t_end (if t is outside of this interval, the frame at t is determined by extrapolation through the first two or the last two frames), the corresponding frame is determined by linear interpolation in the following way:
(rt, qt) = interpolate( path,t)
rt = interpolate_r(path,t)where rt is the position vector to the origin of the frame at path parameter t and qt is the absolute quaternion of the frame at path parameter t.
Example
import Modia3D
using Unitful
r = [ SVector{3,F}(1,0,0),
SVector{3,F}(0,1,0),
SVector{3,F}(0,0,1) ]
q = [ Modia3D.NullQuaternion(F),
Modia3D.qrot1(45u"°"),
Modia3D.qrot2(60u"°")]
path = Modia3D.Path(r,q)
t_end = Modia3D.t_pathEnd(path)
dt = 0.1
stopTime = 2.0
time = 0.0
while time <= stopTime
(rt, qt) = Modia3D.interpolate(path, time*t_end/stopTime)
time += dt
endModia3D.Frames.t_pathEnd — Functiont_end = Modia3D.t_pathEnd(path::[`Modia3D.Path`](@ref))Return the final path parameter tof the last frame in path (path parameter of first frame = 0.0).
Modia3D.Frames.interpolate — Function(rt, qt) = Modia3D.interpolate(path, t)Return position rtand Quaternion qt of path::Modia3D.Path at path parameter t::Number.
Modia3D.Frames.interpolate_r — Functionrt = Modia3D.interpolate_r(path, t)Return position r of path::Modia3D.Path at path parameter t::Number.