Introduction
Introduction
There is no beginning; there is no end; the end of this is open to further exploration and development...
There was a beginning.... July 12, 2015, 7:42 PM https://docs.google.com/document/d/1_6JdZ0VplMFpBeR3QOcV5vhlOGYyn52T4-fITgI6lbc
And well before that even... but that captures the spirit of why matrices with infinitesimal steps is better than quaternions; was an early JS learning example to figure out if quaternions implemented by Three.js somehow worked right... they didn't, so I implemented 'right rotate' which moves the plane perpendicular to a rotation axis; which the matrix defines naturally the three direction vectors that give the up/right/forward direction in a frame...and moved one) Then early 2020, I picked up the research for better rotations, and found an even better rotation method staring us in the face for (160?) years potentially...
A common ground between all rotation transformations and mathematical notations is the notion of axis-angle. (So? Does that make them the projection or the projector? The shadow or the shadow puppet or maybe even the puppeteer?)
Axis-Angle is much like taking a gyroscope, and orienting its axle in a certain direction, then the angle around that axle(axis) is an amount the rotor of the gyroscope is displaced. The axis of rotation of the gyroscope can be represented by a unit direction vector (what is a vector??); and then the unit vector, otherwise just being a '1' can be scaled by the angle of the rotor. But then, consider what the X coordinate of that vector is; it's the total change of the frame rotated around that axis. The coordinates on each axis, independently are the change in the frame's angle around the respective axis.
The X,Y,Z axes, when represented with unit vectors, are scaled by the angles of rotation around each of those axes. The combination of these angles has a effective rotation around their combined axis that is the square-root of the sum of their squares; and the vector divided by the length is the unit axis direction vector.
Rotation is a transformation of a frame around a line progressively through time; at a particular time T, when T=1, that the entirety of the angle is applied, and the transformation of the X, Y and Z axes is at a certain state; this state is its orientation. Although a rotation vector can also represent just a velocity, which is how much the frames orientation changes over time. If you could plot a 4D animation; the axes would start at a fixed, known location, and then scaled the angle by the time from 0 to 1; the tips of each of the axes would follow their own trajectories.
https://d3x0r.github.io/STFRPhysics/3d/index4.html - 'Show Trajectories' option - shows what happens to a point translated as if it had a small forward velocity that did not change in each of the axis directions....
https://d3x0r.github.io/STFRPhysics/3d/indexRelative.html - This has 5 rotations, which are added and subtracted from each other... (1+2=3, 2+3=4, ... 3-2=1(offset), 4-3=2(offset),... ). This also shows the frames each progressively updated, so that the end points of relative curls for each axis results in the same frame orientation. (I'm making a disclaimer that the associated demo will add any clarity to the situation; at least not immediately... would be better with more of a guided tour showing how things are changing)
(repeat/variation)
'What is this?' A system(really just 1 function) of rotation using vectors of angles around 3 fixed axes of rotation could be described by 3 axis of rotation, each with an angle.
Simple addition of the X, Y, and Z axes ( scaled by their angles results in a rotation vector. The total rotation is the square-root of the sum of the squares of the angles( Sqrt[XX+YY+ZZ] ), and the vector divided by that same length is a unit vector that is an axis of rotation. The addition of each of the vector components results in a vector which represents an axis-angle to rotate around.
'Why so many words?' Apparently noone taught this in school; apparently no other formal math system leverages this notion of rotations; instead rotations are based on a rotation which is then rotated which is then rotated; calculating with axis-angle, the notion is really already 3 independent spin axis that add to get a combined rotation vector, which can then be applied; grouping many sequential operations into a single sum and then a multiplication (essentially, and abstractly). SU(2) is very far removed from this space. This space ends up, dare I say, quite 'natural' working in radians for angles (or appropriate scaling from turns to fractions of a turn; this system could benefit more from having sin and cos that took in 0-1 turns and gave back 0-1 unit circle/direction; although having the extra π symbol associated with numbers separates it as a type notion of the number as in programming data types); and that is a rotation vector, as opposed to a linear space vector.
This defines a function 'rotate[]' which a rotation is changed by another rotation, defined by an axis and angle, which is a smooth acceleration within its own frame, will result with a rotation vector which has had the torque applied over the time that the rotation has been rotating, such that the relative location of the toque changes in time. There are also external rotations, which can be done using the same function, but the rotation vector is translated into the frame, and the resulting translation never changes any of the points that are along that rotation vector anyway, so the apparent rotation always happens from the same orientation.
This uses Rodrigues Rotation Formula (https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#The_composition_of_spatial_rotations) and partial exponentiation to perform rotation operations; this is as or more efficient as other matrix methods, but is a continuous function instead of applications of discrete values.
A rotation vector that is 0 length is an identity vector; it causes 0 angular change around any axis.
Spherical coordinates are often used to specify a location on a sphere as an angle from a pole, and an angle around the equator, as is used with latitude and longitude angles for the earth. This is enough to specify a point, or to specify a direction to get to a point from the center, but a full 3D specification also needs to specify the facing direction around that vector. When you're standing at some point on the earth, with the vector from your feet to your head indicating up, you can turn and be facing a specific direction around that vector.
Interactive demo; shows both the rotation vector coordinates, and the associated frame projected on a unit sphere determined by it's up vector.
https://d3x0r.github.io/STFRPhysics/3d/indexSphereMap.html
Rough video explanations...
https://www.youtube.com/watch?v=0Y7fmMtlm3Q
There was a beginning.... July 12, 2015, 7:42 PM https://docs.google.com/document/d/1_6JdZ0VplMFpBeR3QOcV5vhlOGYyn52T4-fITgI6lbc
And well before that even... but that captures the spirit of why matrices with infinitesimal steps is better than quaternions; was an early JS learning example to figure out if quaternions implemented by Three.js somehow worked right... they didn't, so I implemented 'right rotate' which moves the plane perpendicular to a rotation axis; which the matrix defines naturally the three direction vectors that give the up/right/forward direction in a frame...and moved one) Then early 2020, I picked up the research for better rotations, and found an even better rotation method staring us in the face for (160?) years potentially...
A common ground between all rotation transformations and mathematical notations is the notion of axis-angle. (So? Does that make them the projection or the projector? The shadow or the shadow puppet or maybe even the puppeteer?)
Axis-Angle is much like taking a gyroscope, and orienting its axle in a certain direction, then the angle around that axle(axis) is an amount the rotor of the gyroscope is displaced. The axis of rotation of the gyroscope can be represented by a unit direction vector (what is a vector??); and then the unit vector, otherwise just being a '1' can be scaled by the angle of the rotor. But then, consider what the X coordinate of that vector is; it's the total change of the frame rotated around that axis. The coordinates on each axis, independently are the change in the frame's angle around the respective axis.
The X,Y,Z axes, when represented with unit vectors, are scaled by the angles of rotation around each of those axes. The combination of these angles has a effective rotation around their combined axis that is the square-root of the sum of their squares; and the vector divided by the length is the unit axis direction vector.
Rotation is a transformation of a frame around a line progressively through time; at a particular time T, when T=1, that the entirety of the angle is applied, and the transformation of the X, Y and Z axes is at a certain state; this state is its orientation. Although a rotation vector can also represent just a velocity, which is how much the frames orientation changes over time. If you could plot a 4D animation; the axes would start at a fixed, known location, and then scaled the angle by the time from 0 to 1; the tips of each of the axes would follow their own trajectories.
https://d3x0r.github.io/STFRPhysics/3d/index4.html - 'Show Trajectories' option - shows what happens to a point translated as if it had a small forward velocity that did not change in each of the axis directions....
https://d3x0r.github.io/STFRPhysics/3d/indexRelative.html - This has 5 rotations, which are added and subtracted from each other... (1+2=3, 2+3=4, ... 3-2=1(offset), 4-3=2(offset),... ). This also shows the frames each progressively updated, so that the end points of relative curls for each axis results in the same frame orientation. (I'm making a disclaimer that the associated demo will add any clarity to the situation; at least not immediately... would be better with more of a guided tour showing how things are changing)
(repeat/variation)
'What is this?' A system(really just 1 function) of rotation using vectors of angles around 3 fixed axes of rotation could be described by 3 axis of rotation, each with an angle.
Simple addition of the X, Y, and Z axes ( scaled by their angles results in a rotation vector. The total rotation is the square-root of the sum of the squares of the angles( Sqrt[XX+YY+ZZ] ), and the vector divided by that same length is a unit vector that is an axis of rotation. The addition of each of the vector components results in a vector which represents an axis-angle to rotate around.
'Why so many words?' Apparently noone taught this in school; apparently no other formal math system leverages this notion of rotations; instead rotations are based on a rotation which is then rotated which is then rotated; calculating with axis-angle, the notion is really already 3 independent spin axis that add to get a combined rotation vector, which can then be applied; grouping many sequential operations into a single sum and then a multiplication (essentially, and abstractly). SU(2) is very far removed from this space. This space ends up, dare I say, quite 'natural' working in radians for angles (or appropriate scaling from turns to fractions of a turn; this system could benefit more from having sin and cos that took in 0-1 turns and gave back 0-1 unit circle/direction; although having the extra π symbol associated with numbers separates it as a type notion of the number as in programming data types); and that is a rotation vector, as opposed to a linear space vector.
This defines a function 'rotate[]' which a rotation is changed by another rotation, defined by an axis and angle, which is a smooth acceleration within its own frame, will result with a rotation vector which has had the torque applied over the time that the rotation has been rotating, such that the relative location of the toque changes in time. There are also external rotations, which can be done using the same function, but the rotation vector is translated into the frame, and the resulting translation never changes any of the points that are along that rotation vector anyway, so the apparent rotation always happens from the same orientation.
This uses Rodrigues Rotation Formula (https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#The_composition_of_spatial_rotations) and partial exponentiation to perform rotation operations; this is as or more efficient as other matrix methods, but is a continuous function instead of applications of discrete values.
A rotation vector that is 0 length is an identity vector; it causes 0 angular change around any axis.
Spherical coordinates are often used to specify a location on a sphere as an angle from a pole, and an angle around the equator, as is used with latitude and longitude angles for the earth. This is enough to specify a point, or to specify a direction to get to a point from the center, but a full 3D specification also needs to specify the facing direction around that vector. When you're standing at some point on the earth, with the vector from your feet to your head indicating up, you can turn and be facing a specific direction around that vector.
Interactive demo; shows both the rotation vector coordinates, and the associated frame projected on a unit sphere determined by it's up vector.
https://d3x0r.github.io/STFRPhysics/3d/indexSphereMap.html
Rough video explanations...
https://www.youtube.com/watch?v=0Y7fmMtlm3Q
Terms
Terms
https://github.com/d3x0r/STFRPhysics/blob/master/MATH.md#glossary
Frame - This is a multipurpose and vague notion;
1) the generate state of things at an instant in time .
2) the orientation vectors as a matrix or set; the combined notion of forward right and up at a specific moment in time. Might be pictured as a unit cube in some orientation; and the wire frame of the cube is a 'frame'.
Orientation
Rotation
Torque
Position
Velocity
Acceleration
Frame - This is a multipurpose and vague notion;
1) the generate state of things at an instant in time .
2) the orientation vectors as a matrix or set; the combined notion of forward right and up at a specific moment in time. Might be pictured as a unit cube in some orientation; and the wire frame of the cube is a 'frame'.
Orientation
Rotation
Torque
Position
Velocity
Acceleration
Although blahblah has blahblah it's not blahblah.
Although blahblah has blahblah it's not blahblah.
...Although a cat has fur it is not fur;
...and though we say "this space is 3 feet" it's really "that space has 3 feet" (in this case, a measure isn't space, but a space has a measure).
Although a rotation vector may be thought of as an orientation at T=1, it's not really an orientation, it's a vector that describes taking a base frame basis [(1 0 0)(0,1,0)(0,0,1)] and at time T=1 is updated to reflect the specified orientation. Adding rotation vectors is not adding orientations.
I am attempting to keep this more general, not to specifically imply a rigid structure; the idea of up, right, and forward (although I guess maybe the convention is often left or backward instead; but maybe (1) I'm left handed, or (2) when learning math and graphing in school I mostly watched the teacher do it on the board, which makes Y go up and X go to the right, and I always pictured the z axis as going back into the board to the upper-right (although it might also have been out of the board, if you were sort of looking up and under it).. unless it's drawn to the lower left with an arrow that way, then the forward is more of a backward. I have been considering that maybe people pondered graphs by looking at the ground, which makes y forward and z the up direction... or maybe pondering with a piece of paper flat in front of them... then X is right, Y is forward and Z is up; generally this doesn't matter in implementation; if a certain rendering system has a certain convention, the same math generally works, and it goes all the way out to the user input, and for example whether 'W' and 'S' keys(which are meant to move forward and backward) increment Y or Z and whether 'A' and 'D' (which are meant to move left and right) add or subtract to the X coordinate (or more appropriately self labeled arrow keys).
The definitives are
- there is a Euclidean/Minkowski space with X,Y and Z axis that are perpendicular(orthogonal even) to each other
- along each of these axes is a fixed axis of rotation; co-incidental, congruent(?) with each of the mentioned X, Y and Z axis.
...and though we say "this space is 3 feet" it's really "that space has 3 feet" (in this case, a measure isn't space, but a space has a measure).
Although a rotation vector may be thought of as an orientation at T=1, it's not really an orientation, it's a vector that describes taking a base frame basis [(1 0 0)(0,1,0)(0,0,1)] and at time T=1 is updated to reflect the specified orientation. Adding rotation vectors is not adding orientations.
I am attempting to keep this more general, not to specifically imply a rigid structure; the idea of up, right, and forward (although I guess maybe the convention is often left or backward instead; but maybe (1) I'm left handed, or (2) when learning math and graphing in school I mostly watched the teacher do it on the board, which makes Y go up and X go to the right, and I always pictured the z axis as going back into the board to the upper-right (although it might also have been out of the board, if you were sort of looking up and under it).. unless it's drawn to the lower left with an arrow that way, then the forward is more of a backward. I have been considering that maybe people pondered graphs by looking at the ground, which makes y forward and z the up direction... or maybe pondering with a piece of paper flat in front of them... then X is right, Y is forward and Z is up; generally this doesn't matter in implementation; if a certain rendering system has a certain convention, the same math generally works, and it goes all the way out to the user input, and for example whether 'W' and 'S' keys(which are meant to move forward and backward) increment Y or Z and whether 'A' and 'D' (which are meant to move left and right) add or subtract to the X coordinate (or more appropriately self labeled arrow keys).
The definitives are
- there is a Euclidean/Minkowski space with X,Y and Z axis that are perpendicular(orthogonal even) to each other
- along each of these axes is a fixed axis of rotation; co-incidental, congruent(?) with each of the mentioned X, Y and Z axis.
Every Good Boy Deserves Favor?
Every Good Boy Deserves Favor?
(Or; on the rules of systems...)
Rotation vectors have a constraint on the actual directions they can go from any specific point. "where you end up is a matter of where you start" (... )
In the physical world we live in, you could pick any 2 arbitrary 3D points that represent a start and an end of a path. If you choose something like the floor somewhere near you and a point on a roof of a nearby building, you can subtract those points, and get what the straight line to get there is; such that if you went somewhere along that line, but something prevented you from going directly along the line you can subtract and figure out what part of the path was failing, and that if you were able to apply that difference in the frame before, you would end up where you actually wanted to go. But chances are, there's some curve you'll need to follow instead of the straight line. Rotation vectors have similar limitations, and what lines they are allowed to follow are quite non linear.
The `rotate[]` function provides this required path for a straight line, when going from a rotation vector rotated around a rotation vector to another rotation vector. The vector may be scaled by some sort of delta-T or time scalar either shorter or longer than it's unit length; this changes only the amount of rotation around a point. [ (x,y,z) * c = (cx,cy,cz) ] Note: many other parameterizations that can be represented with 3D rotation vectors do not simply scale as a vector. Most of them think of the axis as a function of two of the angles, instead of all 3
angles together. Many omit the third angle entirely, relying purely on the directionality without worrying about facing.
There is always a sort of implied "time" or T associated with rotation vectors and projecting them for various uses. The default is often the constant value 1, and is often already included in the angle, since 1*ang = ang, it's hard to know that it's there.
The relative assignments of up, right and forward are application specific, but are related to the terms yaw, pitch and roll respectively.
- Yaw is a rotation around the up axis; the up axis is calculated based on the current rotation vector at T=1.
- Pitch is a rotation around the right axis; the right axis is calculated based on the current rotation vector at T=1.
- Roll is a rotation around the forward axis; the forward axis is calculated based on the current rotation vector at T=1.
- Turn (later defined as lnQTurn(p,y,r)) is the vector representing the combined rotations of yaw, pitch and roll together. ( pitch[q,p]+yaw[q,y]+roll[q,r] )
On the addition of rotation vectors; if a rotation state is at a specific value, you can relatively compare relative rotations with a subtraction; but the proper rotation through time is not going to be a straight line; but will be an arc through the rotation space.
Rotation vectors have a constraint on the actual directions they can go from any specific point. "where you end up is a matter of where you start" (... )
In the physical world we live in, you could pick any 2 arbitrary 3D points that represent a start and an end of a path. If you choose something like the floor somewhere near you and a point on a roof of a nearby building, you can subtract those points, and get what the straight line to get there is; such that if you went somewhere along that line, but something prevented you from going directly along the line you can subtract and figure out what part of the path was failing, and that if you were able to apply that difference in the frame before, you would end up where you actually wanted to go. But chances are, there's some curve you'll need to follow instead of the straight line. Rotation vectors have similar limitations, and what lines they are allowed to follow are quite non linear.
The `rotate[]` function provides this required path for a straight line, when going from a rotation vector rotated around a rotation vector to another rotation vector. The vector may be scaled by some sort of delta-T or time scalar either shorter or longer than it's unit length; this changes only the amount of rotation around a point. [ (x,y,z) * c = (cx,cy,cz) ] Note: many other parameterizations that can be represented with 3D rotation vectors do not simply scale as a vector. Most of them think of the axis as a function of two of the angles, instead of all 3
angles together. Many omit the third angle entirely, relying purely on the directionality without worrying about facing.
There is always a sort of implied "time" or T associated with rotation vectors and projecting them for various uses. The default is often the constant value 1, and is often already included in the angle, since 1*ang = ang, it's hard to know that it's there.
The relative assignments of up, right and forward are application specific, but are related to the terms yaw, pitch and roll respectively.
- Yaw is a rotation around the up axis; the up axis is calculated based on the current rotation vector at T=1.
- Pitch is a rotation around the right axis; the right axis is calculated based on the current rotation vector at T=1.
- Roll is a rotation around the forward axis; the forward axis is calculated based on the current rotation vector at T=1.
- Turn (later defined as lnQTurn(p,y,r)) is the vector representing the combined rotations of yaw, pitch and roll together. ( pitch[q,p]+yaw[q,y]+roll[q,r] )
On the addition of rotation vectors; if a rotation state is at a specific value, you can relatively compare relative rotations with a subtraction; but the proper rotation through time is not going to be a straight line; but will be an arc through the rotation space.
Quaternion Comparison
Quaternion Comparison
(tenative)
(Quaternions never resulted in what I expected;
When implementing the Quaternion comparison at the end, the initial implementation using " Qrotate[q_,r_]:=(Q[q]**(Q[r])); " Seemed to generate the right curve; but I'd have to reverse the CrossProduct in the rotation function. Then rotate[] and Qrotate[] produced pixel perfect aligned graphs... A=B even. So I took that cross product inverse and applied it to the library, and got https://d3x0r.github.io/STFRPhysics/3d/index4.html with 'use Quaternion [ ]' checked or unchecked, you'd be hard pressed to know it updated; So I went on, and
(Quaternions never resulted in what I expected;
When implementing the Quaternion comparison at the end, the initial implementation using " Qrotate[q_,r_]:=(Q[q]**(Q[r])); " Seemed to generate the right curve; but I'd have to reverse the CrossProduct in the rotation function. Then rotate[] and Qrotate[] produced pixel perfect aligned graphs... A=B even. So I took that cross product inverse and applied it to the library, and got https://d3x0r.github.io/STFRPhysics/3d/index4.html with 'use Quaternion [ ]' checked or unchecked, you'd be hard pressed to know it updated; So I went on, and
Simple Parameterizations
Simple Parameterizations
The basic rotation vector is a unit direction vector scaled by an angle of rotation. This is just 3 coordinates, representing the rotation around each of the 3 spatial axes.
Many of the 2 parameter parameterizations leave the facing unspecified.
lnQ[x,y,z] - just joins elements into a group.
lnQexp[q] - return a quaternion (? wolfram specific version ?) (reference only, not unit tested)
lnQn[q] - return the rotation axis (Any rotation axis if the length of q is 0).
lnQfromAxisAngle[axis,angle] - returns [normalized-axis]*[angle].
lnQfromRT[r,t] - This uses an arc-length from the pole as [r] and an angle [t(heta)] to result with a rotation vector whose up is in the specified direction.
lnQfromRTS[r,t,s] - This uses an arc-length from the pole as [r], an angle [t(heta)] and the spin [s] to result with a rotation vector whose up is in the specified direction, with a specified facing.
lnQfromLatLong[lat,long] - This builds a rotation vector whose up direction is specified by latitude and longitude. This has an extended range that encodes a range of 4pi latitude and longitude semi-uniquely. Each of latitude and longitude have unique coordinates within a range of 4pi; but in combination using a range of 4pi in one direction limits the effective (unique) range of the other to 2pi.
lnQfromDirection[x] - for some direction vector [x], compute a rotation vector that has up in that direction; facing is unspecified (in this case it's tilt or spin rather than facing, since it's an outward facing calculation),
Many of the 2 parameter parameterizations leave the facing unspecified.
lnQ[x,y,z] - just joins elements into a group.
lnQexp[q] - return a quaternion (? wolfram specific version ?) (reference only, not unit tested)
lnQn[q] - return the rotation axis (Any rotation axis if the length of q is 0).
lnQfromAxisAngle[axis,angle] - returns [normalized-axis]*[angle].
lnQfromRT[r,t] - This uses an arc-length from the pole as [r] and an angle [t(heta)] to result with a rotation vector whose up is in the specified direction.
lnQfromRTS[r,t,s] - This uses an arc-length from the pole as [r], an angle [t(heta)] and the spin [s] to result with a rotation vector whose up is in the specified direction, with a specified facing.
lnQfromLatLong[lat,long] - This builds a rotation vector whose up direction is specified by latitude and longitude. This has an extended range that encodes a range of 4pi latitude and longitude semi-uniquely. Each of latitude and longitude have unique coordinates within a range of 4pi; but in combination using a range of 4pi in one direction limits the effective (unique) range of the other to 2pi.
lnQfromDirection[x] - for some direction vector [x], compute a rotation vector that has up in that direction; facing is unspecified (in this case it's tilt or spin rather than facing, since it's an outward facing calculation),
In[]:=
(*Constructavector*)lnQ[a_,b_,c_]:={a,b,c};(*exp(q);lnQexp[]resultsintheexponentiatedvectorasaquaternion{w,x,y,z}*)lnQexp[q_]:={Cos[Norm[q]/2],Sin[Norm[q]/2]*q[1]/Norm[q],Sin[Norm[q]/2]*q[2]/Norm[q],Sin[Norm[q]/2]*q[3]/Norm[q]};(*Convertsarotationvectorto{x,y,z,angle}wherex,y,zaretheunitdirectionvector,andangleisthespecifiedrotationangle*)lnQn[q_]:=Module[{lnqLen},(lnqLen=Norm[q];If[lnqLen==0,{1,0,0}(*thisshouldALWAYSbeaunitvector;sincethelengthis0,thisspecific directiondoesn'tmatter*),{q[[1]]/lnqLen,q[[2]]/lnqLen,q[[3]]/lnqLen}])];(*Buildaroationvectorfromadirectionvector(whichmaybeanon-unitvector),andarotationanglearoundthespecifiedaxis.*)lnQfromAxisAngle[ax_,ag_]:=Module[{tmp,ax,ag},(tmp=Norm[ax];If[tmp==0,{0,0,0},ax*ag/tmp])];(*BuildarotationvectorfromanRandThetapolarcoodinate,theRistakenasanangleawayfromtheZaxispole. theRcoordinatehasarangeof(0-4pi). the(T)hetacoordinatehasaranteof(0-2pi).*)lnQfromRT[r_,t_]:=Module[{ang,n},(ang=ArcSin[Sin[t]*Sin[r/2]]*2+Pi;If[Mod[Abs[ang],2*Pi]==0,{0,0,0},n=ang/Sin[ang/2];{n*Cos[r/2],n*Cos[t]Sin[r/2],0}])];(*BuildarotationvectorfromRandTheta,andthespinaroundthatpoint*)lnQfromRTS[r_,t_,s_]:=Module[{ang,n},(ang=ArcSin[Sin[s+t]*Sin[r/2]]*2+Pi;If[Mod[Abs[ang],2*Pi]==0,{0,0,0},n=ang/Sin[ang/2];{n*Cos[s]*Cos[r/2],n*Cos[s+t]Sin[r/2],n*Sin[s]Cos[r/2]}])];(*ThisisusedinfromLatLongtoprovideacontinuousrotationpathfrom0to4piforbothLatitudeandLongitudevalues.Thisallowsmakingaspacefillingcurve forasinglecoverofrotationvectorspace.*)constGrid={{0,Pi*2,Pi*2,0},{Pi*2,0,0,Pi*2},{Pi*2,0,0,Pi*2},{0,Pi*2,Pi*2,0}};(*SpecifyrotationvectorusingLatitudeandLongitudecoordinateshaveaneffectiverangeof0-4pi*)lnQfromLatLong[lat_,lng_]:=Module[{gridlat,gridlng,gridLatOct,gridLngOct,spin},(gridlat=Floor[Abs[lat]/Pi];gridlng=Floor[Abs[lng]/Pi];gridLatOct=Floor[gridlat/4];gridLngOct=Floor[gridlng/4];spin=constGrid[[gridlat]][[gridlng]]+(gridLatOct+gridLngOct)*4*Pi;{Sin[lng]*(lat+spin),0,Cos[lng]*(lat+spin)})];(*useadirectionvectortosettheUPofaframeinthatdirection*)lnQfromDirection[x_]:=Module[{l2},l2=(Abs[x[[1]]]+Abs(x[[3]]));If[l2==0 ,If[x[[2]]>0,{0,1,0},{0,-1,0}](*assumingYisalsoUP*) norm1=Sqrt[x[[1]]^2+x[[3]]^2]; ArcCos[x[[2]]/Norm[x]]*{x[[3]]/norm1,0,-x[[1]]/norm1}]]
Rotation Functions
Rotation Functions
The rotate[] function is used to rotate a rotation; which is a different behavior than rotating a vector in linear space. While being rotated, the relative direction of the rotation is calculated including the original rotation; such that as the original frame is being rotated, the axis it rotates around changes. This has the effect of co-mutating the rotation vector being rotated and the rotation vector it is rotated by over time; it might be said that
while rotations don't commute, they do co-mute.
rotate[q,ax,ang] function takes a rotation vector[q] to rotate, and an axis[ax] and angle[ang] to rotate around.
rotateBy[q,q2] can be used to rotate [q] around a rotation vector [q2].
rotateVector[v,q] can be used to rotate a linear 3D vector[v] around a rotation vector[q].
while rotations don't commute, they do co-mute.
rotate[q,ax,ang] function takes a rotation vector[q] to rotate, and an axis[ax] and angle[ang] to rotate around.
rotateBy[q,q2] can be used to rotate [q] around a rotation vector [q2].
rotateVector[v,q] can be used to rotate a linear 3D vector[v] around a rotation vector[q].
In[]:=
(*assumesaxisarenormalizedalready;axis,angle,axis,angleresultwithaxis*anglemaythrowdivideby0;butthatmeanstheresultingangleis0,andtherotation vectorshouldbe{0,0,0}.*)rotateUnchecked[q_,th_,ax_,ang_]:=(rotang=2*ArcCos[((q.ax)*(Cos[(ang+th)/2]-Cos[(ang-th)/2])+Cos[(ang-th)/2]+Cos[(ang+th)/2])/2];rotang/(2*Sin[rotang/2])*(Cross[ax,q]*(Cos[(ang-th)/2]-Cos[(ang+th)/2])+ax*(Sin[(ang-th)/2]+Sin[(ang+th)/2])+q*(Sin[(ang+th)/2]-Sin[(ang-th)/2])));(*includessingularitycheckswheredividebyzeromighthappen...expects[ax]tobeaunitnormal*)rotate[q_,ax_,ang_]:=Module[{qnRot,rotang},(th=Sqrt[q[[1]]^2+q[[2]]^2+q[[3]]^2];If[th==0,ax*ang(*iforiginalrotationis0;resultisjusttheappliedrotation*),(qnRot=q/th;(*normalizeq*)rotang=2*ArcCos[((qnRot.ax)*(Cos[(ang+th)/2]-Cos[(ang-th)/2])+Cos[(ang-th)/2]+Cos[(ang+th)/2])/2];If[Mod[rotang,2*Pi]==0,{0,0,0},rotang/(2*Sin[rotang/2])*(Cross[ax,qnRot]*(Cos[(ang-th)/2]-Cos[(ang+th)/2])+ax*(Sin[(ang-th)/2]+Sin[(ang+th)/2])+qnRot*(Sin[(ang+th)/2]-Sin[(ang-th)/2]))])])];(*convertrotationvectorstoaxis-anglewithaxisaunitdirectionvector*)rotateBy[q_,q2_]:=If[Norm[q]==0,q2,rotateUnchecked[q/Norm[q],Norm[q],q2/Norm[q2],Norm[q2]]];
Rotate a point around a rotation vector...
Axis Functions
Axis Functions
Some utility functions to return the direction vectors for a specific rotation vector.
Basis matrix result is the combination of all the directional vectors.
Also, simple functions to rotate a rotation around its relative right, up, and/or forward axes.
The basis generated is probably transposed from the matrix often carried in other math; it is compatible with lnQfromBasis[], which means that a transpose probably needs to apply before using that function.
On the one hand it's easier to build the direction vectors and append them; also means the vectors of the axis normals are in-order in memory and can be immediately use for forward/right/up calculations.
Basis matrix result is the combination of all the directional vectors.
Also, simple functions to rotate a rotation around its relative right, up, and/or forward axes.
The basis generated is probably transposed from the matrix often carried in other math; it is compatible with lnQfromBasis[], which means that a transpose probably needs to apply before using that function.
On the one hand it's easier to build the direction vectors and append them; also means the vectors of the axis normals are in-order in memory and can be immediately use for forward/right/up calculations.
These are some utility functions to rotate the frame around the common directions (yaw/pitch/roll), and turn allows turning simultaneously with all 3.
This defines some functions using the above functions to rotate around some known fixed locations; like when computing the physics of a plane, or car, it's often practical to think about rotations around the relative X, Y and Z axis.
The relationship of yaw, pitch and roll to the axis is arbitrary and
This defines some functions using the above functions to rotate around some known fixed locations; like when computing the physics of a plane, or car, it's often practical to think about rotations around the relative X, Y and Z axis.
The relationship of yaw, pitch and roll to the axis is arbitrary and
Is rotate vector the same as adding the scaled axes? (yes.)
- some simple tests of above utility functions
From Matrix...
From Matrix...
This converts from basis vectors to a rotation vector.
This assumes that the X vector component of the basis represents the right direction, Y is the up, and Z is forward.
The basis expected is probably transposed from the matrix often carried in math; it is compatible with lnQbasis[], which means that a transpose probably needs to apply to that matrix.
This assumes that the X vector component of the basis represents the right direction, Y is the up, and Z is forward.
The basis expected is probably transposed from the matrix often carried in math; it is compatible with lnQbasis[], which means that a transpose probably needs to apply to that matrix.
Look at...
Look at...
A generally useful orientation parameterization is forward and right, so the tilt around a direction is controlled.
This might be done using the lnQfromBasis function above.
- lnQlookAt[forward,up] results in a rotation vector whose Z and Y axes of the frame match the specified direction vectors.
- lnQlookTo[forward,right] a variation of the above which specifies the right instead of up direction.
This might be done using the lnQfromBasis function above.
- lnQlookAt[forward,up] results in a rotation vector whose Z and Y axes of the frame match the specified direction vectors.
- lnQlookTo[forward,right] a variation of the above which specifies the right instead of up direction.
Hopf Fibration/Compositions of 3 Rotations
Hopf Fibration/Compositions of 3 Rotations
Hopf Fibration calculation.
Actually more properly Hopf Fiber; it currently has fixed axis to rotate around;
The Hopf fibration classically consists of a set of these closed rings, instead of iterating with an analog function, each loop is computed with the same fiber step.
There are 3 rotations, [ax0] which is the actual thing rotating, [ax1] which it is rotated around, and [ax2] which that composite is finally rotated around. The iteration does 1 loop around [ax1] and [loops] count of loops around [ax2].
- hopf[dt,total,loops] computes a rotation for [dt] of [total] steps; instead of 1000, one might use 1 instead. [loops] controls how many sub-loops are taken for 1 rotation around axis1.
- hopfAxis[dt,total,loops,ax0,ax1,ax2] this variation lets you specify all 3 rotation parts. [ax0] is a proper rotation, [ax1] and [ax2] are treated only as rotation axis directions.
Actually more properly Hopf Fiber; it currently has fixed axis to rotate around;
The Hopf fibration classically consists of a set of these closed rings, instead of iterating with an analog function, each loop is computed with the same fiber step.
There are 3 rotations, [ax0] which is the actual thing rotating, [ax1] which it is rotated around, and [ax2] which that composite is finally rotated around. The iteration does 1 loop around [ax1] and [loops] count of loops around [ax2].
- hopf[dt,total,loops] computes a rotation for [dt] of [total] steps; instead of 1000, one might use 1 instead. [loops] controls how many sub-loops are taken for 1 rotation around axis1.
- hopfAxis[dt,total,loops,ax0,ax1,ax2] this variation lets you specify all 3 rotation parts. [ax0] is a proper rotation, [ax1] and [ax2] are treated only as rotation axis directions.
This is a basic Hopf fiber graph; this is only showing the 3D rotation coordinates; each point in this represents an orientation of a frame.
Geodesic Rotations/Parallel Frame Transport
Geodesic Rotations/Parallel Frame Transport
lnQfromRT and lnQfromRTS functions generate a graph of rotation points that covers a +/-2pi range of radius(latitude) and +/-pi range of angle around the sphere (longitude).
They take an arc-length [r] from the pole, and [dt] delta-Theta relative to the pole; facing some forward.
The lnQfromRTS[r,t,s] also takes a parameter to bias the spin; this has the effective of tilting the whole plane of rotations.
A single cover, of some particular orientation at the origin pole is parallel transported along any [theta] from the pole for any length of [r]. There are unique rotation vectors for 0-2pi and 2pi-4pi range of R, such that you don't get back to your initial rotation vector for 720 degrees.
https://d3x0r.github.io/STFRPhysics/3d/indexSphereMap3.html
They take an arc-length [r] from the pole, and [dt] delta-Theta relative to the pole; facing some forward.
The lnQfromRTS[r,t,s] also takes a parameter to bias the spin; this has the effective of tilting the whole plane of rotations.
A single cover, of some particular orientation at the origin pole is parallel transported along any [theta] from the pole for any length of [r]. There are unique rotation vectors for 0-2pi and 2pi-4pi range of R, such that you don't get back to your initial rotation vector for 720 degrees.
https://d3x0r.github.io/STFRPhysics/3d/indexSphereMap3.html
Duplicate test of the above, testing that the other parametric function is equivalent; only shows one plane
Example of a narrow range of theta with 95% of 4pi walk for R... which almost gets back to start..
This is an example of the asymmetric rotations, that for 2 pi, every rotation vector magnitude is pi+x , while for the other half it is pi-x where x is the angle off of pi/2.
This is an example of the asymmetric rotations, that for 2 pi, every rotation vector magnitude is pi+x , while for the other half it is pi-x where x is the angle off of pi/2.
Applying a general [s]pin/facing - biases to another plane; there are infinite planes representing the facing around specified normals.
Plot of the normals represented above...
Other Frame Alignment Utilities
Other Frame Alignment Utilities
https://d3x0r.github.io/STFRPhysics/3d/indexSphereMap.html Interactive demo, and links to more information and sources.
Weyl Curvature https://en.wikipedia.org/wiki/Tidal_force basis (biases the 'facing' at origin pole to be like https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Field_tidal.svg/435px-Field_tidal.svg.png )
These utility functions create the orientation assuming the Y axis is up, X is right(left), and Z is forward.
The up is controlled by the position of the 0.
They position the direction of up so 1 unit up is on a sphere, and then control the facing around that or the direction of the tangent bivectors.
- lnQasWeyl[r,t] creates a rotation vector representing a frame at the origin with tidal force forward/right facings.
- lnQasPolarAlign[r,t] biases the rotation vector such that the forward of the rotation vector is aligned towards the pole (inverse Weyl) (forward/Z towards the pole)
- lnQasStereo[r,t] basis the rotation vector as a stereo projection - dividing by the [r]; but since these are log-quaternions that's actually just subtracting [r].
- lnQasOther[r,t] This is just the inverse of Stereo; no notable character.
https://d3x0r.github.io/STFRPhysics/3d/indexSphereMap.html Interactive demo, and links to more information and sources.
Weyl Curvature https://en.wikipedia.org/wiki/Tidal_force basis (biases the 'facing' at origin pole to be like https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Field_tidal.svg/435px-Field_tidal.svg.png )
These utility functions create the orientation assuming the Y axis is up, X is right(left), and Z is forward.
The up is controlled by the position of the 0.
They position the direction of up so 1 unit up is on a sphere, and then control the facing around that or the direction of the tangent bivectors.
- lnQasWeyl[r,t] creates a rotation vector representing a frame at the origin with tidal force forward/right facings.
- lnQasPolarAlign[r,t] biases the rotation vector such that the forward of the rotation vector is aligned towards the pole (inverse Weyl) (forward/Z towards the pole)
- lnQasStereo[r,t] basis the rotation vector as a stereo projection - dividing by the [r]; but since these are log-quaternions that's actually just subtracting [r].
- lnQasOther[r,t] This is just the inverse of Stereo; no notable character.
Example Weyl Curvature graph... this could be
The lnQasStereo funtion generates something that looks like a toroid in rotation space... (the projection is squished in just the wrong dimension)
Blow is the normal direction plot - which is a sphere cover.
Blow is the normal direction plot - which is a sphere cover.
External Notebook Interface? do I really have to litter the above with all the module stuff??
Quaternion Implementation
Quaternion Implementation
Test generally that rotate works... convert to quaternion, and multiply or rotate axis angles.
Quaternion First failure....
The first resulting axis...
This uses Quaternion Math to attempt to generate Hopf fibration rotation graph; the reverse calculation from Quaternion to Rotation Vector is potentially lossy and non-reversible; it can sometimes exactly store and recover a rotation vector, but after math, the relative biasing of the vector result is lost. Also, the quaternion, after rotation, is often no longer a Unit Quaternion, and no longer describes a pure rotation.
this isn't right...
Matrix Faux-simulation
Matrix Faux-simulation
Same thing with Matrices...?
The initial multiplication of matrices fails terribly resulting in {0,x,0} as a multiplier.
Final result isn't so great; there should really be an infinitesimal scaling... or a progressive application of the small transform at each point instead of a calculation from the start to the end...
But the graph does end at terminal points, at which point it flips over to the other side of the graph (where there are long straight lines are discontinuities to the graph.
The initial multiplication of matrices fails terribly resulting in {0,x,0} as a multiplier.
Final result isn't so great; there should really be an infinitesimal scaling... or a progressive application of the small transform at each point instead of a calculation from the start to the end...
But the graph does end at terminal points, at which point it flips over to the other side of the graph (where there are long straight lines are discontinuities to the graph.
This is a different graph... not sure where the difference is; this is also a Hopf Fibration pattern... but not the expected one.
This is like the initial rotation matrix was near 0... (above example with Pi/100 as the initial vector)
This is like the initial rotation matrix was near 0... (above example with Pi/100 as the initial vector)