Perl extension for SO3 rotations

Internal representation: SO3s are blessed refs to strings of size 3*3*sizeof(double) which contain the rotation matrix elements in standard C order. THIS IS PART OF THE OFFICIAL INTERFACE, so you may use this information, if you want. (It simply doesn't make much sense to inherit from purely mathematical data types like this one, so this doesn't hurt.) Note: whenever the text below says "d" is used for angles in degrees, any string starting with a lowercase "d" will work. Same goes for "r" for rad. If you entirely leave it away, default is "r". So you have much freedom in choosing those terms which are most descriptive and most readable. Note: some textbooks on Mechanics (like the very good and very influential one by Goldstein) follow the convention (e1') ( ) (e1) (e2') = ( M ) (e2) (e3') ( ) (e3) This is not very fortunate, since it introduces some nasty ambiguity: it's easy to misinterpret the "vector-rotation matrix" M as the coefficient-rotation matrix, which, however, is just M^T. Matrix/vector calculus is exploited best if one agrees to write coefficient vectors as column vectors and the "array of base vectors" as a row vector (e1 e2 e3). Just look here: (a1) a1*e1 + a2*e2 + a3*e3 = (e1 e2 e3) (a2) (a3) Therefore, WE use the convention (a1') ( ) (a1) (a2') = ( M ) (a2) (a3') ( ) (a3) ( ) (e1 e2 e3) = (e1' e2' e3') ( M ) ( ) For details, see e.g. "Misner, Thorne, Wheeler: Gravitation". Unfortunately, the "wrong way" is rather widespread. Even OpenGL seems to want us to think this way. Please try not to get too confused about this; or better, if you are confused: yes, it's not entirely trivial what's going on here. Our three-dimensional space *is* a bit complicated. But there is a recipe to master it: practice. Once you can think of one constellation in two different coordinate systems, you have won. In rigid body mechanics, it's best to think of this M as the matrix, which, when multiplied-right with a column space-coordinate vector (cscv) gives the corresponding column body-coordinate vector (cbcv). $rotation=Math::SO3->new("zr" => 3.14159/2, "xr" => 3.14159/4, "zr" => 3.14159/8); Create a new SO3-rotation matrix. You may specify an arbitrary number of rotations performed on the identity matrix. In the above case, if you think of $rotation as the matrix translating column-space-coordinate-vectors to column-body-coordinate-vectors (from here on called cscv->cbcv), these rotations you specify here will be applied to the body, rotating the body round one of its body axes. Important: Leftmost rotation will be applied first. "zr" means rotate round z-axis, angle is in rad (full turn= 2pi rad); "xd" would mean: rotate round x-axis, angle is in degrees (full turn=360 degrees). Can be mixed. May also act as a copying constructor, as in: $copy=$rotation->new(). $rotation->invert(); Invert a rotation. $rotation->turn("zr" => 3.14159/2, "xr" => 3.14159/4); Just as you can specify rotations at SO3 creation, you may add a few more later on. Although "numerical drift" can build up, it is not possible for the rotation to get noticeably non-orthogonal. $rotation->turn_round_axis((pack "d3", 1,1,1), 30, "degrees"); Turn the body round the axis given in space coordinates. $rotation->combine($rotation_after); left-multiplies with $rotation_after, that is, executes $rotation_after after $rotation, in the sense defined above. $rotation->translate_vectors($vec1, $vec2, $vec3, $vec4, @other_vectors); Destructively replace each single one of a list of cscv's by the corresponding cbcv's. Note that vectors must be packed-double-strings: $vec=pack("d3",$xcoord,$ycoord,$zcoord); Note: if vectors are "longer", say, like pack("d4", 5,8,10,1), only the first three coordinates will be replaced. This is very useful when working with homogenous coordinates. $rotation->inv_translate_vectors($vec1, $vec2, $vec3, $vec4, @other_vectors); Just the other way round, going cbcv -> cscv. ($angle, $dir)=$rotation->turning_angle_and_dir("d"); Euler's theorem states that in three dimensions, every combination of rotations may be expressed as a single rotation round a given direction. This determines angle and direction Say "d" if you want degrees, "r" for rad. FIXME code for this function is a bit weird and really should be reviewed. So please, you NASA guys, don't use it to compute RTG-satellite trajectories. ($phi, $theta, $psi)=$rotation->euler_angles_zxz("d"); Returns just the famous Euler angles corresponding to a rotation. Specify "d" if you want degrees, "r" for rad. Note: this is designed for speed, and may, for a very small fraction of all possible angles, give bad results due to division by a small quantity. ($heading, $pitch, $roll)=$rotation->euler_angles_yxz("d"); Standard zxz euler angles have one problem: if theta is very small, phi and psi rotations nearly go in the same direction, therefore, it's a bit difficult to see from coordinates if two rotations are very similar or are absolutely not. This is an alternative angle specification which is very common in aeronautics. Probably just the thing you need if you want to build a flight simulator. Note: accuracy see above. $rotation->format_matrix(); $rotation->format_matrix("%16.8f"); Computes a string "[[m00 m01 m02][m10 m11 m12][m20 m21 m22]]" displaying the matrix elements. Optionally, a sprintf format-string may be specified for the matrix elements. Default is "%10.5f". $rotation->format_eigenvector(); $rotation->format_eigenvector("%16.8f"); Similarly, computes a string like "<rotate 92.06153 deg round [ 0.88972 0.07784 -0.44982]>" $rotation->format_euler_zxz(); $rotation->format_euler_zxz("%16.8f"); Similarly, computes a string like "<D_z(psi= 330.00000 deg) D_x(theta= 80.00000 deg) D_z(phi= 340.00000 deg)>" $rotation->format_euler_yxz(); $rotation->format_euler_yxz("%16.8f"); Just the same, but string is like "<D_z(heading= 338.30608 deg) D_x(pitch= -24.51349 deg) D_z(roll= 348.25034 deg)>" Basically, these functions were added as a quick way to get debugging info. Therefore, all angles are given in degrees, since these are more readable.

There is no official package available for openSUSE Leap 15.1


openSUSE Tumbleweed