%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%22marimo%3E%3D0.23.9%22%2C%20%22numpy%3E%3D2.0%22%2C%20%22matplotlib%3E%3D3.9%22%2C%20%22pandas%3E%3D2.2%22%2C%20%22sympy%3E%3D1.13%22%2C%20%22urllib3%3E%3D2.2%22%5D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.25.2%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Rigid-body%20transformations%20in%20three%20dimensions%0A%0A%20%20%20%20%3E%20Marcos%20Duarte%2C%20Renato%20Naville%20Watanabe%3Cbr%3E%0A%20%20%20%20%3E%20%5BLaboratory%20of%20Biomechanics%20and%20Motor%20Control%5D(https%3A%2F%2Fbmclab.pesquisa.ufabc.edu.br%2F)%3Cbr%3E%0A%20%20%20%20%3E%20Federal%20University%20of%20ABC%2C%20Brazil%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20How%20to%20use%20this%20guide%0A%0A%20%20%20%20In%20a%20plane%2C%20rotations%20are%20easy.%20One%20angle%20describes%20an%20orientation%2C%20and%20angles%20add%3A%20turn%20by%2030%C2%B0%20and%20then%20by%2020%C2%B0%2C%20and%20you%20have%20turned%20by%2050%C2%B0%2C%20in%20whichever%20order%20you%20like.%20In%20three%20dimensions%20neither%20statement%20survives.%20An%20orientation%20needs%20three%20angles%2C%20and%20the%20result%20of%20two%20rotations%20depends%20on%20the%20order%20in%20which%20they%20are%20made.%20Almost%20everything%20that%20is%20hard%20about%20three-dimensional%20kinematics%20comes%20from%20that%20one%20fact.%0A%0A%20%20%20%20This%20notebook%20builds%20the%20tools%20to%20handle%20it.%20It%20starts%20with%20the%20rotation%20matrix%2C%20the%20object%20that%20describes%20an%20orientation%20without%20ambiguity%2C%20and%20then%20turns%20to%20Euler%20angles%2C%20the%20three%20numbers%20that%20people%20actually%20report%2C%20with%20their%20conventions%20and%20their%20failure%20mode%2C%20the%20gimbal%20lock.%20It%20ends%20where%20motion%20analysis%20does%3A%20combining%20rotation%20and%20translation%2C%20first%20on%20a%20static%20example%20from%20a%20textbook%20and%20then%20on%20every%20frame%20of%20a%20real%20walking%20trial.%0A%0A%20%20%20%20Read%20it%20in%20order%20and%20run%20each%20cell%20as%20you%20reach%20it.%20Where%20you%20find%20a%20**Challenge**%20or%20a%20set%20of%20**Guiding%20questions**%2C%20stop%20and%20answer%20on%20a%20scratchpad%20before%20moving%20on.%20Several%20of%20them%20ask%20you%20to%20predict%20a%20result%20*before*%20the%20code%20prints%20it.%20Make%20the%20prediction%3B%20a%20wrong%20guess%20that%20the%20code%20then%20corrects%20teaches%20more%20than%20a%20right%20one.%0A%0A%20%20%20%20The%20numbered%20**Exercises**%20come%20with%20solutions%2C%20folded%20away%20under%20each%20exercise.%20Try%20the%20exercise%20first%2C%20and%20open%20the%20solution%20only%20to%20check%20your%20answer%20or%20when%20you%20are%20stuck.%0A%0A%20%20%20%20The%20notebook%20follows%20the%20same%20rationale%20as%20%5BRigid-body%20transformations%20in%20a%20plane%20(2D)%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_2d.py)%20and%20skips%20the%20fundamental%20concepts%20covered%20there%2C%20so%20if%20you%20have%20not%20read%20that%20notebook%20yet%2C%20read%20it%20first.%20You%20will%20also%20need%20matrix%20multiplication%20(see%20%5BMatrix%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmatrix.py))%2C%20and%20the%20construction%20of%20a%20basis%20from%20three%20markers%2C%20explained%20in%20%5BDetermination%20of%20a%20coordinate%20system%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fcoordinate_system.py)%20and%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py).%0A%0A%20%20%20%20**Challenge%200.**%20Take%20a%20book%20and%20hold%20it%20upright%20in%20front%20of%20you%2C%20with%20its%20spine%20towards%20you.%20Turn%20it%20by%2090%C2%B0%20about%20a%20horizontal%20axis%20pointing%20to%20your%20right%2C%20and%20then%20by%2090%C2%B0%20about%20the%20vertical%20axis.%20Note%20where%20the%20spine%20ends%20up.%20Now%20start%20again%20and%20make%20the%20same%20two%20turns%20in%20the%20opposite%20order.%20Sketch%20both%20results%3B%20the%20section%20on%20rotation%20shows%20the%20answer.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Codman's%20paradox%0A%0A%20%20%20%20Stand%20up%20and%20let%20your%20right%20arm%20hang%20at%20your%20side%2C%20with%20the%20palm%20against%20your%20thigh%20and%20the%20thumb%20pointing%20forward.%20Keeping%20the%20elbow%20straight%2C%20make%20three%20movements%2C%20each%20a%20quarter%20of%20a%20turn%3A%0A%0A%20%20%20%201.%20Raise%20the%20arm%20forward%20until%20it%20is%20horizontal%20(90%C2%B0%20of%20flexion).%0A%20%20%20%202.%20Keeping%20it%20horizontal%2C%20swing%20it%20out%20to%20the%20side%20(90%C2%B0%20of%20horizontal%20abduction).%0A%20%20%20%203.%20Lower%20it%20to%20your%20side%20again%20(90%C2%B0%20of%20adduction).%0A%0A%20%20%20%20The%20arm%20is%20back%20where%20it%20started.%20Now%20look%20at%20your%20palm.%0A%0A%20%20%20%20This%20is%20known%20as%20Codman's%20paradox%2C%20after%20the%20surgeon%20Ernest%20Codman%2C%20who%20described%20it%20while%20studying%20the%20shoulder.%20None%20of%20the%20three%20movements%20turned%20the%20arm%20about%20its%20own%20long%20axis%2C%20and%20yet%20the%20hand%20did%20not%20come%20back%20the%20way%20it%20left.%20It%20is%20not%20really%20a%20paradox%20(Politti%20et%20al.%2C%201998)%3A%20it%20is%20what%20rotations%20in%20three%20dimensions%20do%2C%20and%20later%20in%20this%20notebook%20you%20will%20compute%20it%20with%20three%20matrices.%0A%0A%20%20%20%20**Guiding%20questions%200.**%0A%0A%20%20%20%201.%20Where%20does%20your%20palm%20face%20at%20the%20end%3F%20At%20which%20of%20the%20three%20movements%2C%20if%20any%2C%20did%20your%20arm%20turn%20about%20its%20long%20axis%3F%0A%20%20%20%202.%20Make%20the%20same%20three%20movements%20in%20a%20different%20order%3A%20first%20raise%20the%20arm%20sideways%20to%20horizontal%2C%20then%20swing%20it%20forward%2C%20then%20lower%20it%20in%20front%20of%20you.%20Do%20you%20end%20in%20the%20same%20place%3F%0A%20%20%20%203.%20If%20three%20quarter%20turns%20about%20three%20perpendicular%20axes%20can%20add%20up%20to%20a%20turn%20about%20a%20fourth%20axis%2C%20what%20does%20that%20tell%20you%20about%20adding%20angles%20in%20three%20dimensions%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Python%20setup%0A%0A%20%20%20%20NumPy%20does%20the%20numerical%20work%2C%20%5BSymPy%5D(https%3A%2F%2Fwww.sympy.org)%20the%20symbolic%20work%2C%20and%20Matplotlib%20the%20figures.%20The%20helper%20functions%20%60CCS%60%2C%20which%20draws%20coordinate%20systems%20in%203D%2C%20and%20%60read_trc%60%2C%20which%20reads%20motion%20capture%20files%2C%20come%20from%20the%20%60functions%60%20folder%20of%20this%20repository%20and%20are%20loaded%20where%20they%20are%20first%20needed.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20sympy%20as%20sym%0A%20%20%20%20import%20matplotlib%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%0A%20%20%20%20np.set_printoptions(precision%3D4%2C%20suppress%3DTrue)%20%20%23%20suppress%20scientific%20notation%20for%20small%20numbers%0A%20%20%20%20matplotlib.rc(%22axes%22%2C%20labelsize%3D13%2C%20titlesize%3D14)%0A%20%20%20%20matplotlib.rc(%22xtick%22%2C%20labelsize%3D11)%0A%20%20%20%20matplotlib.rc(%22ytick%22%2C%20labelsize%3D11)%0A%20%20%20%20matplotlib.rc(%22legend%22%2C%20fontsize%3D11)%0A%20%20%20%20return%20np%2C%20plt%2C%20sym%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Many%20results%20in%20this%20notebook%20are%20matrices%2C%20symbolic%20or%20numerical.%20The%20function%20below%20displays%20one%20as%20a%20formula%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20show_matrix(lhs%2C%20matrix%2C%20digits%3DNone)%3A%0A%20%20%20%20%22%22%22Display%20%60lhs%60%20%3D%20%60matrix%60%20as%20LaTeX%2C%20for%20a%20SymPy%20or%20NumPy%20matrix.%0A%0A%20%20%20%20With%20%60digits%60%2C%20the%20entries%20are%20evaluated%20numerically%20to%20that%20number%20of%0A%20%20%20%20significant%20digits%2C%20and%20entries%20that%20are%20zero%20to%20within%20rounding%20are%20shown%0A%20%20%20%20as%20zero.%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20sympy%20as%20sym%0A%0A%20%20%20%20M%20%3D%20sym.Matrix(matrix)%0A%20%20%20%20if%20digits%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20M%20%3D%20M.n(digits%2C%20chop%3DTrue)%0A%20%20%20%20return%20mo.md(rf%22%24%24%7Blhs%7D%20%3D%20%7Bsym.latex(M%2C%20mat_str%3D'matrix')%7D%24%24%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Rigid%20bodies%20and%20their%20transformations%0A%0A%20%20%20%20The%20kinematics%20of%20a%20rigid%20body%20is%20completely%20described%20by%20its%20pose%2C%20that%20is%2C%20its%20position%20and%20orientation%20in%20space%2C%20and%20by%20the%20changes%20of%20pose%2C%20translation%20and%20rotation.%20In%20three-dimensional%20space%2C%20at%20least%20three%20coordinates%20and%20three%20angles%20are%20needed%20to%20describe%20the%20pose%20of%20a%20rigid%20body%3A%20six%20degrees%20of%20freedom.%0A%0A%20%20%20%20In%20motion%20analysis%2C%20to%20describe%20the%20translation%20and%20rotation%20of%20a%20rigid%20body%20with%20respect%20to%20a%20coordinate%20system%2C%20we%20typically%20attach%20another%20coordinate%20system%20to%20the%20rigid%20body%20and%20determine%20the%20transformation%20between%20the%20two%20coordinate%20systems.%0A%0A%20%20%20%20A%20transformation%20is%20any%20function%20mapping%20a%20set%20to%20another%20set.%20For%20the%20kinematics%20of%20rigid%20bodies%20we%20are%20interested%20only%20in%20the%20rigid%2C%20or%20Euclidean%2C%20transformations%20(denoted%20SE(3)%20for%20three-dimensional%20space)%2C%20because%20they%20preserve%20the%20distance%20between%20every%20pair%20of%20points%20of%20the%20body%2C%20which%20is%20rigid%20by%20definition.%20Translations%20and%20rotations%20are%20rigid%20transformations.%20A%20reflection%20also%20preserves%20distances%2C%20but%20it%20turns%20a%20right-handed%20coordinate%20system%20into%20a%20left-handed%20one%2C%20which%20is%20usually%20not%20of%20interest.%20In%20turn%2C%20rigid%20transformations%20are%20examples%20of%20%5Baffine%20transformations%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FAffine_transformation)%3B%20shear%20and%20scaling%20are%20other%20affine%20transformations%2C%20which%20do%20not%20preserve%20lengths.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Translation%0A%0A%20%20%20%20A%20pure%20three-dimensional%20translation%20of%20a%20rigid%20body%20(or%20of%20a%20coordinate%20system%20attached%20to%20it)%20in%20relation%20to%20another%20rigid%20body%20(with%20another%20coordinate%20system)%20is%20illustrated%20in%20the%20figure%20below.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-1%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Ftranslation3D.png%3Fraw%3D1%22%20width%3D450%20alt%3D%22translation%203D%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-1%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20A%20point%20in%20three-dimensional%20space%20represented%20in%20two%20coordinate%20systems%2C%20with%20one%20coordinate%20system%20translated.%3C%2Fspan%3E%0A%0A%20%20%20%20The%20position%20of%20the%20point%20%24%5Cmathbf%7BP%7D%24%2C%20originally%20described%20in%20the%20%24xyz%24%20(local)%20coordinate%20system%20but%20now%20described%20in%20the%20%24%5Cmathbf%7BXYZ%7D%24%20(Global)%20coordinate%20system%2C%20is%20in%20vector%20form%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BP_l%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20or%2C%20in%20terms%20of%20its%20components%2C%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20%5Cmathbf%7BP_X%7D%20%3D%26%20%5Cmathbf%7BL_X%7D%20%2B%20%5Cmathbf%7BP%7D_x%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Y%7D%20%3D%26%20%5Cmathbf%7BL_Y%7D%20%2B%20%5Cmathbf%7BP%7D_y%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Z%7D%20%3D%26%20%5Cmathbf%7BL_Z%7D%20%2B%20%5Cmathbf%7BP%7D_z%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20in%20matrix%20form%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Cmathbf%7BP_X%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Y%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Z%7D%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Cmathbf%7BL_X%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BL_Y%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BL_Z%7D%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%2B%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Cmathbf%7BP%7D_x%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP%7D_y%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP%7D_z%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20In%20classical%20mechanics%2C%20this%20is%20an%20example%20of%20a%20%5BGalilean%20transformation%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FGalilean_transformation)%2C%20the%20same%20one%20that%20relates%20a%20runner%20on%20a%20treadmill%20to%20a%20runner%20on%20the%20ground%20in%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py).%0A%0A%20%20%20%20For%20example%2C%20if%20the%20local%20coordinate%20system%20is%20translated%20by%20%24%5Cmathbf%7BL_G%7D%3D%5B1%2C%202%2C%203%5D%24%20in%20relation%20to%20the%20Global%20coordinate%20system%2C%20a%20point%20with%20coordinates%20%24%5Cmathbf%7BP_l%7D%3D%5B4%2C%205%2C%206%5D%24%20in%20the%20local%20coordinate%20system%20has%20the%20position%20%24%5Cmathbf%7BP_G%7D%3D%5B5%2C%207%2C%209%5D%24%20in%20the%20Global%20coordinate%20system%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_LG%20%3D%20np.array(%5B1%2C%202%2C%203%5D)%20%20%23%20NumPy%20array%0A%20%20%20%20_Pl%20%3D%20np.array(%5B4%2C%205%2C%206%5D)%0A%20%20%20%20_PG%20%3D%20_LG%20%2B%20_Pl%0A%0A%20%20%20%20print(%22PG%20%3D%22%2C%20_PG)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20same%20operation%20works%20for%20several%20points%20at%20once%2C%20one%20per%20row%3A%20NumPy%20adds%20the%20translation%20to%20every%20row%20(this%20is%20called%20broadcasting).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_LG%20%3D%20np.array(%5B1%2C%202%2C%203%5D)%0A%20%20%20%20_Pl%20%3D%20np.array(%5B%5B1%2C%202%2C%203%5D%2C%20%5B4%2C%205%2C%206%5D%2C%20%5B7%2C%208%2C%209%5D%5D)%20%20%23%202D%20array%20with%203%20rows%20and%203%20columns%0A%20%20%20%20_PG%20%3D%20_LG%20%2B%20_Pl%0A%0A%20%20%20%20print(%22PG%20%3D%5Cn%22%2C%20_PG)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Exercise%201.**%20A%20force%20plate%20is%20installed%20with%20its%20axes%20parallel%20to%20those%20of%20the%20laboratory%2C%20and%20the%20origin%20of%20its%20coordinate%20system%20is%20at%20%24%5Cmathbf%7BL_G%7D%20%3D%20%5B0.40%2C%5C%2C%200.00%2C%5C%2C%200.30%5D%24%20m%20in%20the%20laboratory.%20The%20plate%20reports%20the%20centre%20of%20pressure%20of%20a%20foot%20at%20%24%5Cmathbf%7BP_l%7D%20%3D%20%5B0.12%2C%5C%2C%200.00%2C%5C%2C%200.25%5D%24%20m%20in%20its%20own%20coordinate%20system.%20Where%20is%20the%20centre%20of%20pressure%20in%20the%20laboratory%3F%20And%20where%2C%20in%20the%20coordinate%20system%20of%20the%20plate%2C%20is%20a%20heel%20marker%20measured%20at%20%24%5B0.55%2C%5C%2C%200.05%2C%5C%2C%200.50%5D%24%20m%20in%20the%20laboratory%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%201%0A%20%20%20%20With%20parallel%20axes%2C%20changing%20coordinate%20system%20is%20a%20pure%20translation.%20From%20the%20plate%20to%20the%20laboratory%2C%20add%20the%20position%20of%20the%20plate's%20origin%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BP_l%7D%20%3D%20%5B0.40%20%2B%200.12%2C%5C%3B%200.00%20%2B%200.00%2C%5C%3B%200.30%20%2B%200.25%5D%20%3D%20%5B0.52%2C%5C%3B%200.00%2C%5C%3B%200.55%5D%5C%3B%5Cmathrm%7Bm%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20From%20the%20laboratory%20to%20the%20plate%2C%20subtract%20it%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BP_G%7D%20-%20%5Cmathbf%7BL_G%7D%20%3D%20%5B0.55%20-%200.40%2C%5C%3B%200.05%20-%200.00%2C%5C%3B%200.50%20-%200.30%5D%20%3D%20%5B0.15%2C%5C%3B%200.05%2C%5C%3B%200.20%5D%5C%3B%5Cmathrm%7Bm%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20heel%20marker%20is%205%20cm%20above%20the%20surface%20of%20the%20plate%2C%20as%20a%20marker%20on%20a%20shoe%20should%20be.%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Rotation%0A%0A%20%20%20%20A%20pure%20three-dimensional%20rotation%20of%20an%20%24xyz%24%20(local)%20coordinate%20system%20in%20relation%20to%20another%2C%20%24%5Cmathbf%7BXYZ%7D%24%20(Global)%2C%20coordinate%20system%2C%20and%20the%20position%20of%20a%20point%20in%20these%20two%20coordinate%20systems%2C%20are%20illustrated%20in%20the%20next%20figure.%20Remember%20that%20this%20is%20equivalent%20to%20describing%20a%20rotation%20between%20two%20rigid%20bodies.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-2%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Frotation3D.png%3Fraw%3D1%22%20width%3D450%20alt%3D%22rotation%203D%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-2%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20A%20point%20in%20three-dimensional%20space%20represented%20in%20two%20coordinate%20systems%2C%20with%20one%20coordinate%20system%20rotated.%3C%2Fspan%3E%0A%0A%20%20%20%20An%20important%20characteristic%20of%20rotations%20in%20three-dimensional%20space%20is%20that%20angles%20cannot%20be%20treated%20as%20vectors%3A%20the%20result%20of%20a%20sequence%20of%20rotations%20of%20a%20rigid%20body%20about%20different%20axes%20depends%20on%20the%20order%20of%20the%20rotations%2C%20as%20the%20next%20figure%20shows%20for%20the%20book%20of%20Challenge%200.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-3%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Frotationsseqs2.png%3Fraw%3D1%22%20width%3D700%20alt%3D%22sequences%20of%20rotations%20of%20a%20book%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-3%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20The%20result%20of%20a%20sequence%20of%20rotations%20about%20different%20axes%20of%20a%20coordinate%20system%20depends%20on%20the%20order%20of%20the%20rotations.%20In%20the%20first%20example%20(first%20row)%2C%20the%20rotations%20are%20about%20a%20Global%20(fixed)%20coordinate%20system.%20In%20the%20second%20example%20(second%20row)%2C%20the%20rotations%20are%20about%20a%20local%20(rotating)%20coordinate%20system.%3C%2Fspan%3E%0A%0A%20%20%20%20Compare%20the%20figure%20with%20your%20sketches%20from%20Challenge%200.%20Notice%20also%20something%20that%20the%20figure%20shows%20without%20saying%3A%20the%20two%20orders%20*about%20the%20fixed%20axes*%20give%20results%20that%20reappear%2C%20in%20the%20opposite%20order%2C%20*about%20the%20rotating%20axes*.%20We%20will%20come%20back%20to%20that.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Determination%20of%20the%20rotation%20matrix%20using%20direction%20cosines%0A%0A%20%20%20%20As%20for%20rotations%20in%20two%20dimensions%2C%20we%20can%20calculate%20the%20rotation%20matrix%20that%20describes%20the%20rotation%20of%20the%20%24xyz%24%20(local)%20coordinate%20system%20in%20relation%20to%20the%20%24%5Cmathbf%7BXYZ%7D%24%20(Global)%20coordinate%20system%20from%20the%20direction%20cosines%20between%20the%20axes%20of%20the%20two%20coordinate%20systems%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%7D%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cmathbf%7BX%7Dx%20%26%20%5Ccos%5Cmathbf%7BX%7Dy%20%26%20%5Ccos%5Cmathbf%7BX%7Dz%20%5C%5C%0A%20%20%20%20%5Ccos%5Cmathbf%7BY%7Dx%20%26%20%5Ccos%5Cmathbf%7BY%7Dy%20%26%20%5Ccos%5Cmathbf%7BY%7Dz%20%5C%5C%0A%20%20%20%20%5Ccos%5Cmathbf%7BZ%7Dx%20%26%20%5Ccos%5Cmathbf%7BZ%7Dy%20%26%20%5Ccos%5Cmathbf%7BZ%7Dz%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Note%2C%20however%2C%20that%20for%20rotations%20about%20more%20than%20one%20axis%20these%20angles%20do%20not%20lie%20in%20the%20main%20planes%20(%24%5Cmathbf%7BXY%2C%20YZ%2C%20ZX%7D%24)%20of%20the%20%24%5Cmathbf%7BXYZ%7D%24%20coordinate%20system%2C%20as%20illustrated%20in%20the%20figure%20below%20for%20the%20direction%20angles%20of%20the%20%24y%24%20axis%20alone.%20Determining%20these%20angles%20by%20simple%20inspection%2C%20as%20we%20did%20in%20two%20dimensions%2C%20is%20no%20longer%20simple.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-4%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Fdirectioncosine3D.png%3Fraw%3D1%22%20width%3D260%20alt%3D%22direction%20angles%203D%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-4%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20Definition%20of%20the%20direction%20angles%20of%20the%20%24y%24%20axis%20of%20the%20local%20coordinate%20system%20in%20relation%20to%20the%20%24%5Cmathbf%7BXYZ%7D%24%20Global%20coordinate%20system.%3C%2Fspan%3E%0A%0A%20%20%20%20The%20nine%20angles%20in%20the%20matrix%20are%20also%20obviously%20redundant%2C%20since%20only%20three%20angles%20are%20needed%20to%20describe%20the%20orientation%20of%20a%20rigid%20body%20in%20three-dimensional%20space.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Determination%20of%20the%20rotation%20matrix%20using%20the%20basis%20method%0A%0A%20%20%20%20As%20described%20in%20%5BRigid-body%20transformations%20in%20a%20plane%20(2D)%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_2d.py)%2C%20the%20columns%20(or%20rows)%20of%20the%203D%20rotation%20matrix%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20(or%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24)%20between%20two%20coordinate%20systems%20are%20the%20versors%20of%20the%20basis%20of%20the%20rotated%20coordinate%20system.%0A%0A%20%20%20%20Suppose%20we%20have%20measured%20the%20positions%20of%20at%20least%20three%20noncollinear%20markers%20placed%20on%20the%20rigid%20body.%20Let's%20calculate%20a%20basis%20from%20these%20positions%2C%20and%20then%20the%20rotation%20matrix.%20Given%20three%20markers%20%24%5Cmathbf%7Bm_1%7D%24%2C%20%24%5Cmathbf%7Bm_2%7D%24%2C%20%24%5Cmathbf%7Bm_3%7D%24%2C%20a%20basis%20of%20three%20orthogonal%20versors%20can%20be%20found%20as%20follows%20(see%20%5BDetermination%20of%20a%20coordinate%20system%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fcoordinate_system.py)%20for%20this%20recipe%20in%20detail)%3A%0A%0A%20%20%20%20-%20First%20axis%2C%20%24%5Cmathbf%7Bv_1%7D%24%3A%20the%20vector%20%24%5Cmathbf%7Bm_2%7D-%5Cmathbf%7Bm_1%7D%24.%0A%20%20%20%20-%20Second%20axis%2C%20%24%5Cmathbf%7Bv_2%7D%24%3A%20the%20cross%20product%20between%20the%20vectors%20%24%5Cmathbf%7Bv_1%7D%24%20and%20%24%5Cmathbf%7Bm_3%7D-%5Cmathbf%7Bm_1%7D%24.%0A%20%20%20%20-%20Third%20axis%2C%20%24%5Cmathbf%7Bv_3%7D%24%3A%20the%20cross%20product%20between%20the%20vectors%20%24%5Cmathbf%7Bv_1%7D%24%20and%20%24%5Cmathbf%7Bv_2%7D%24.%0A%0A%20%20%20%20Each%20of%20these%20vectors%20is%20then%20normalized%2C%20resulting%20in%20three%20orthogonal%20versors.%0A%0A%20%20%20%20For%20example%2C%20given%20the%20positions%20%24%5Cmathbf%7Bm_1%7D%20%3D%20%5B1%2C0%2C0%5D%24%2C%20%24%5Cmathbf%7Bm_2%7D%20%3D%20%5B0%2C1%2C0%5D%24%2C%20%24%5Cmathbf%7Bm_3%7D%20%3D%20%5B0%2C0%2C1%5D%24%2C%20a%20basis%20can%20be%20found%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20m1%20%3D%20np.array(%5B1%2C%200%2C%200%5D)%0A%20%20%20%20m2%20%3D%20np.array(%5B0%2C%201%2C%200%5D)%0A%20%20%20%20m3%20%3D%20np.array(%5B0%2C%200%2C%201%5D)%0A%0A%20%20%20%20v1%20%3D%20m2%20-%20m1%0A%20%20%20%20v2%20%3D%20np.cross(v1%2C%20m3%20-%20m1)%0A%20%20%20%20v3%20%3D%20np.cross(v1%2C%20v2)%0A%0A%20%20%20%20v1%20%3D%20v1%20%2F%20np.linalg.norm(v1)%0A%20%20%20%20v2%20%3D%20v2%20%2F%20np.linalg.norm(v2)%0A%20%20%20%20v3%20%3D%20v3%20%2F%20np.linalg.norm(v3)%0A%20%20%20%20print(%22Versors%3A%22%2C%20%22%5Cnv1%20%3D%22%2C%20v1%2C%20%22%5Cnv2%20%3D%22%2C%20v2%2C%20%22%5Cnv3%20%3D%22%2C%20v3)%0A%0A%20%20%20%20_RGl%20%3D%20np.array(%5Bv1%2C%20v2%2C%20v3%5D).T%20%20%23%20or%20np.vstack((v1%2C%20v2%2C%20v3)).T%0A%20%20%20%20print(%22%5CnRotation%20matrix%20RGl%3A%5Cn%22%2C%20_RGl)%0A%20%20%20%20return%20v1%2C%20v2%2C%20v3%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20A%20rotation%20matrix%20is%20not%20just%20any%20matrix.%20Its%20columns%20are%20orthogonal%20versors%2C%20so%20it%20is%20**orthonormal**%3A%20%24%5Cmathbf%7BR%7D%5ET%5Cmathbf%7BR%7D%20%3D%20%5Cmathbf%7BI%7D%24%2C%20which%20means%20that%20its%20inverse%20is%20its%20transpose.%20And%20because%20the%20basis%20is%20right-handed%2C%20its%20determinant%20is%20%24%2B1%24.%20Let's%20check%20both%2C%20together%20with%20the%20norms%20and%20the%20dot%20products%20of%20the%20versors%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20v1%2C%20v2%2C%20v3)%3A%0A%20%20%20%20_RGl%20%3D%20np.array(%5Bv1%2C%20v2%2C%20v3%5D).T%0A%0A%20%20%20%20print(%22Norm%20of%20each%20versor%3A%22%2C%20np.linalg.norm(v1)%2C%20np.linalg.norm(v2)%2C%20np.linalg.norm(v3))%0A%20%20%20%20print(f%22Dot%20products%3A%20v1.v2%20%3D%20%7Bnp.dot(v1%2C%20v2)%3A.1e%7D%2C%20v1.v3%20%3D%20%7Bnp.dot(v1%2C%20v3)%3A.1e%7D%2C%20v2.v3%20%3D%20%7Bnp.dot(v2%2C%20v3)%3A.1e%7D%22)%0A%20%20%20%20print(%22%5CnRGl%5ET%20RGl%20%3D%5Cn%22%2C%20(_RGl.T%20%40%20_RGl).round(10)%20%2B%200.0)%0A%20%20%20%20print(f%22%5Cndet(RGl)%20%3D%20%7Bnp.linalg.det(_RGl)%3Ag%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20However%2C%20we%20have%20the%20same%20problem%20as%20with%20the%20rotation%20matrix%20deduced%20from%20the%20direction%20cosines%3A%20there%20is%20no%20simple%20way%20to%20read%20angles%20of%20rotation%20off%20this%20matrix.%0A%0A%20%20%20%20**Exercise%202.**%20Which%20of%20the%20following%20matrices%20are%20rotation%20matrices%3F%20For%20those%20that%20are%2C%20find%20the%20axis%20and%20the%20angle%20of%20the%20rotation%20by%20inspection.%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BA%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200%20%26%201%20%26%200%20%5C%5C%201%20%26%200%20%26%200%20%5C%5C%200%20%26%200%20%26%201%20%5Cend%7Bbmatrix%7D%2C%20%5Cquad%0A%20%20%20%20%5Cmathbf%7BB%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200%20%26%20-1%20%26%200%20%5C%5C%201%20%26%200%20%26%200%20%5C%5C%200%20%26%200%20%26%201%20%5Cend%7Bbmatrix%7D%2C%20%5Cquad%0A%20%20%20%20%5Cmathbf%7BC%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%201%20%26%200%20%26%200%20%5C%5C%200%20%26%200.8%20%26%20-0.6%20%5C%5C%200%20%26%200.6%20%26%200.8%20%5Cend%7Bbmatrix%7D%2C%20%5Cquad%0A%20%20%20%20%5Cmathbf%7BD%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%201%20%26%200.1%20%26%200%20%5C%5C%200%20%26%201%20%26%200%20%5C%5C%200%20%26%200%20%26%201%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%202%0A%20%20%20%20A%20rotation%20matrix%20needs%20both%20properties%3A%20orthonormal%20columns%20and%20a%20determinant%20of%20%24%2B1%24.%0A%0A%20%20%20%20-%20%24%5Cmathbf%7BA%7D%24%20has%20orthonormal%20columns%2C%20but%20its%20determinant%20is%20%24-1%24.%20It%20swaps%20the%20%24%5Cmathbf%7BX%7D%24%20and%20%24%5Cmathbf%7BY%7D%24%20axes%2C%20a%20reflection%20in%20the%20plane%20%24%5Cmathbf%7BX%7D%20%3D%20%5Cmathbf%7BY%7D%24%2C%20which%20would%20turn%20a%20right-handed%20coordinate%20system%20into%20a%20left-handed%20one.%20Not%20a%20rotation.%0A%20%20%20%20-%20%24%5Cmathbf%7BB%7D%24%20is%20orthonormal%20with%20determinant%20%24%2B1%24.%20Its%20third%20column%20is%20%24%5B0%2C%200%2C%201%5D%24%2C%20so%20%24%5Cmathbf%7BZ%7D%24%20is%20unchanged%20and%20the%20axis%20is%20%24%5Cmathbf%7BZ%7D%24.%20Its%20first%20column%2C%20the%20image%20of%20%24%5Cmathbf%7BX%7D%24%2C%20is%20%24%5B0%2C%201%2C%200%5D%24%3A%20%24%5Cmathbf%7BX%7D%24%20was%20turned%20into%20%24%5Cmathbf%7BY%7D%24%2C%20a%20rotation%20of%20%24%2B90%5Eo%24%20about%20%24%5Cmathbf%7BZ%7D%24.%0A%20%20%20%20-%20%24%5Cmathbf%7BC%7D%24%20is%20orthonormal%20with%20determinant%20%240.8%5E2%20%2B%200.6%5E2%20%3D%201%24.%20Its%20first%20column%20is%20%24%5B1%2C%200%2C%200%5D%24%2C%20so%20the%20axis%20is%20%24%5Cmathbf%7BX%7D%24%2C%20and%20comparing%20it%20with%20the%20elemental%20rotation%20about%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Ccos%5Calpha%20%3D%200.8%24%20and%20%24%5Csin%5Calpha%20%3D%200.6%24%3A%20%24%5Calpha%20%3D%20%5Carctan2(0.6%2C%200.8)%20%3D%2036.87%5Eo%24.%0A%20%20%20%20-%20%24%5Cmathbf%7BD%7D%24%20has%20determinant%20%24%2B1%24%2C%20but%20it%20is%20not%20orthonormal%3A%20its%20second%20column%2C%20%24%5B0.1%2C%201%2C%200%5D%24%2C%20has%20norm%20%24%5Csqrt%7B1.01%7D%24%20and%20is%20not%20perpendicular%20to%20the%20first.%20It%20is%20a%20shear%2C%20which%20changes%20angles%20and%20lengths.%20A%20determinant%20of%20%24%2B1%24%20alone%20is%20not%20enough.%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Euler%20angles%0A%0A%20%20%20%20There%20are%20different%20ways%20to%20describe%20a%20three-dimensional%20rotation%20of%20a%20rigid%20body%20(or%20of%20a%20coordinate%20system).%20The%20most%20straightforward%20would%20probably%20be%20spherical%20coordinates%2C%20but%20it%20would%20be%20difficult%20to%20give%20them%20an%20anatomical%20or%20clinical%20interpretation.%20The%20solution%20most%20often%20employed%20in%20biomechanics%20is%20Euler%20angles.%20Under%20certain%20conditions%20Euler%20angles%20have%20an%20anatomical%20interpretation%2C%20but%20the%20representation%20also%20has%20caveats%2C%20as%20we%20will%20see.%0A%0A%20%20%20%20In%20the%2018th%20century%2C%20%5BLeonhard%20Euler%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FLeonhard_Euler)%20showed%20that%20two%20three-dimensional%20coordinate%20systems%20with%20a%20common%20origin%20can%20be%20related%20by%20a%20sequence%20of%20up%20to%20three%20elemental%20rotations%20about%20the%20axes%20of%20the%20local%20coordinate%20system%2C%20where%20no%20two%20successive%20rotations%20may%20be%20about%20the%20same%20axis.%20The%20angles%20of%20these%20rotations%20are%20now%20known%20as%20%5BEuler%20(or%20Eulerian)%20angles%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FEuler_angles).%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-5%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F8%2F85%2FEuler2a.gif%22%20width%3D300%20alt%3D%22Euler%20angles%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-5%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20Euler%20angles%3A%20a%20way%20to%20reach%20any%20orientation%20using%20a%20specific%20sequence%20of%20elemental%20rotations%20(%3Ca%20href%3D%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FEuler_angles%22%3Eimage%20from%20Wikipedia%3C%2Fa%3E).%3C%2Fspan%3E%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Elemental%20rotations%0A%0A%20%20%20%20First%2C%20let's%20look%20at%20rotations%20about%20a%20fixed%20Global%20coordinate%20system%2C%20as%20we%20did%20in%20two%20dimensions.%20The%20next%20figure%20illustrates%20elemental%20rotations%20of%20the%20local%20coordinate%20system%20about%20each%20axis%20of%20the%20fixed%20Global%20coordinate%20system.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-6%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Frotations.png%3Fraw%3D1%22%20width%3D700%20alt%3D%22elemental%20rotations%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-6%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20Elemental%20rotations%20of%20the%20%24xyz%24%20coordinate%20system%20about%20each%20axis%2C%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Cmathbf%7BY%7D%24%20and%20%24%5Cmathbf%7BZ%7D%24%2C%20of%20the%20fixed%20%24%5Cmathbf%7BXYZ%7D%24%20coordinate%20system.%20For%20clarity%2C%20the%20axis%20of%20each%20rotation%20is%20drawn%20perpendicular%20to%20the%20page.%3C%2Fspan%3E%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Rotations%20about%20the%20fixed%20coordinate%20system%0A%0A%20%20%20%20The%20rotation%20matrices%20for%20the%20elemental%20rotations%20about%20each%20axis%20of%20the%20fixed%20%24%5Cmathbf%7BXYZ%7D%24%20coordinate%20system%20(rotations%20of%20the%20local%20coordinate%20system%20in%20relation%20to%20the%20Global%20coordinate%20system)%20are%3A%0A%0A%20%20%20%20About%20the%20%24%5Cmathbf%7BX%7D%24%20axis%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%2C%5C%2CX%7D%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%201%20%26%200%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%200%20%26%20%5Csin%5Calpha%20%26%20%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20About%20the%20%24%5Cmathbf%7BY%7D%24%20axis%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%2C%5C%2CY%7D%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cbeta%20%26%200%20%26%20%5Csin%5Cbeta%20%5C%5C%0A%20%20%20%200%20%26%201%20%26%200%20%5C%5C%0A%20%20%20%20-%5Csin%5Cbeta%20%26%200%20%26%20%5Ccos%5Cbeta%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20About%20the%20%24%5Cmathbf%7BZ%7D%24%20axis%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%2C%5C%2CZ%7D%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cgamma%20%26%20-%5Csin%5Cgamma%20%26%200%5C%5C%0A%20%20%20%20%5Csin%5Cgamma%20%26%20%5Ccos%5Cgamma%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20These%20are%20the%20rotation%20matrices%20of%20the%20two-dimensional%20case%20plus%20the%20terms%20for%20the%20third%20axes%20of%20the%20local%20and%20Global%20coordinate%20systems%2C%20which%20stay%20parallel.%20To%20see%20why%20those%20terms%20are%20ones%20and%20zeros%2C%20remember%20that%20they%20are%20direction%20cosines.%20The%20cosines%20between%20%24%5Cmathbf%7BX%7Dx%24%2C%20%24%5Cmathbf%7BY%7Dy%24%20and%20%24%5Cmathbf%7BZ%7Dz%24%2C%20for%20the%20elemental%20rotations%20about%20the%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Cmathbf%7BY%7D%24%20and%20%24%5Cmathbf%7BZ%7D%24%20axes%20respectively%2C%20are%20all%201%2C%20because%20those%20axes%20are%20parallel%20(%24%5Ccos%200%5Eo%24).%20The%20other%20cosines%20in%20the%20same%20row%20and%20column%20are%20zero%2C%20because%20the%20axis%20of%20each%20rotation%20is%20perpendicular%20to%20the%20other%20axes%20of%20the%20coordinate%20systems%20(%24%5Ccos%2090%5Eo%24).%0A%0A%20%20%20%20Let's%20write%20the%20three%20matrices%20as%20Python%20functions%20of%20an%20angle%20in%20degrees%3B%20we%20will%20use%20them%20throughout%20the%20notebook%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20rotX(angle)%3A%0A%20%20%20%20%22%22%22Elemental%20rotation%20matrix%20about%20the%20fixed%20X%20axis%20(angle%20in%20degrees).%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20t%20%3D%20np.radians(angle)%0A%20%20%20%20return%20np.array(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20np.cos(t)%2C%20-np.sin(t)%5D%2C%20%5B0%2C%20np.sin(t)%2C%20np.cos(t)%5D%5D)%0A%0A%0A%40app.function%0Adef%20rotY(angle)%3A%0A%20%20%20%20%22%22%22Elemental%20rotation%20matrix%20about%20the%20fixed%20Y%20axis%20(angle%20in%20degrees).%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20t%20%3D%20np.radians(angle)%0A%20%20%20%20return%20np.array(%5B%5Bnp.cos(t)%2C%200%2C%20np.sin(t)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B-np.sin(t)%2C%200%2C%20np.cos(t)%5D%5D)%0A%0A%0A%40app.function%0Adef%20rotZ(angle)%3A%0A%20%20%20%20%22%22%22Elemental%20rotation%20matrix%20about%20the%20fixed%20Z%20axis%20(angle%20in%20degrees).%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20t%20%3D%20np.radians(angle)%0A%20%20%20%20return%20np.array(%5B%5Bnp.cos(t)%2C%20-np.sin(t)%2C%200%5D%2C%20%5Bnp.sin(t)%2C%20np.cos(t)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20where%20does%20the%20vector%20%24%5B1%2C%200%2C%200%5D%24%20end%20up%20after%20a%20rotation%20of%2090%C2%B0%20about%20%24%5Cmathbf%7BZ%7D%24%20followed%20by%20a%20rotation%20of%2090%C2%B0%20about%20%24%5Cmathbf%7BX%7D%24%3F%20And%20in%20the%20opposite%20order%3F%20(Each%20new%20rotation%20about%20a%20fixed%20axis%20multiplies%20the%20previous%20result%20from%20the%20left.)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_v%20%3D%20np.array(%5B1%2C%200%2C%200%5D)%0A%0A%20%20%20%20print(%22First%20Z%2C%20then%20X%3A%22%2C%20(rotX(90)%20%40%20rotZ(90)%20%40%20_v).round(4)%20%2B%200.0)%0A%20%20%20%20print(%22First%20X%2C%20then%20Z%3A%22%2C%20(rotZ(90)%20%40%20rotX(90)%20%40%20_v).round(4)%20%2B%200.0)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20first%20rotation%2C%20about%20%24%5Cmathbf%7BZ%7D%24%2C%20takes%20%24%5B1%2C0%2C0%5D%24%20to%20%24%5B0%2C1%2C0%5D%24%2C%20and%20the%20rotation%20about%20%24%5Cmathbf%7BX%7D%24%20then%20lifts%20it%20to%20%24%5B0%2C0%2C1%5D%24.%20In%20the%20opposite%20order%2C%20the%20rotation%20about%20%24%5Cmathbf%7BX%7D%24%20leaves%20%24%5B1%2C0%2C0%5D%24%20where%20it%20is%2C%20because%20the%20vector%20lies%20on%20the%20axis%20of%20rotation%2C%20and%20the%20rotation%20about%20%24%5Cmathbf%7BZ%7D%24%20then%20takes%20it%20to%20%24%5B0%2C1%2C0%5D%24.%20Two%20quarter%20turns%2C%20two%20different%20results%3A%20matrix%20multiplication%20is%20not%20commutative%2C%20and%20neither%20are%20rotations.%0A%0A%20%20%20%20**Exercise%203.**%20And%20two%20half%20turns%3F%20A%20trampolinist%20makes%20a%20half%20somersault%2C%20%24180%5Eo%24%20about%20the%20medio-lateral%20axis%20%24%5Cmathbf%7BZ%7D%24%20of%20the%20laboratory%2C%20and%20a%20half%20turn%2C%20%24180%5Eo%24%20about%20the%20vertical%20axis%20%24%5Cmathbf%7BY%7D%24%2C%20both%20about%20the%20fixed%20axes.%20Does%20the%20order%20matter%3F%20At%20the%20end%2C%20where%20do%20the%20athlete's%20front%2C%20initially%20%24%5B1%2C%200%2C%200%5D%24%2C%20and%20head%2C%20initially%20%24%5B0%2C%201%2C%200%5D%24%2C%20point%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo%2C%20np)%3A%0A%20%20%20%20_somersault_first%20%3D%20rotY(180)%20%40%20rotZ(180)%20%20%23%20first%20Z%2C%20then%20Y%0A%20%20%20%20_turn_first%20%3D%20rotZ(180)%20%40%20rotY(180)%20%20%23%20first%20Y%2C%20then%20Z%0A%20%20%20%20_same%20%3D%20np.allclose(_somersault_first%2C%20_turn_first)%0A%20%20%20%20_half_turn_x%20%3D%20np.allclose(_somersault_first%2C%20rotX(180))%0A%20%20%20%20_front%20%3D%20(_somersault_first%20%40%20np.array(%5B1%2C%200%2C%200%5D)).round(4)%20%2B%200.0%0A%20%20%20%20_head%20%3D%20(_somersault_first%20%40%20np.array(%5B0%2C%201%2C%200%5D)).round(4)%20%2B%200.0%0A%0A%20%20%20%20mo.accordion(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Solution%20to%20Exercise%203%22%3A%20mo.vstack(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20show_matrix(r%22%5Cmathbf%7BR_Y%7D(180%5Eo)%5C%2C%5Cmathbf%7BR_Z%7D(180%5Eo)%22%2C%20_somersault_first%2C%20digits%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20show_matrix(r%22%5Cmathbf%7BR_Z%7D(180%5Eo)%5C%2C%5Cmathbf%7BR_Y%7D(180%5Eo)%22%2C%20_turn_first%2C%20digits%3D3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22The%20two%20orders%20give%20the%20same%20matrix%20(same%3A%20%7B_same%7D)%2C%20and%20it%20is%20a%20half%20turn%20about%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20r%22%24%5Cmathbf%7BX%7D%24%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20f%22%20(equal%20to%20a%20rotation%20of%20180%C2%B0%20about%20X%3A%20%7B_half_turn_x%7D).%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22The%20order%20does%20not%20matter%20here%3A%20half%20turns%20about%20two%20perpendicular%20axes%20commute%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22and%20together%20they%20make%20a%20half%20turn%20about%20the%20third%20axis.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20f%22The%20athlete's%20front%20ends%20at%20%7B_front%7D%2C%20facing%20the%20original%20direction%20again%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20f%22and%20the%20head%20at%20%7B_head%7D%3A%20upside%20down.%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22So%20the%20rule%20is%20that%20the%20order%20of%20rotations%20*can*%20matter%2C%20not%20that%20it%20always%20does.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22When%20in%20doubt%2C%20a%20product%20of%20two%20matrices%20is%20quicker%20than%20an%20argument.%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Rotations%20about%20the%20local%20coordinate%20system%0A%0A%20%20%20%20The%20rotation%20matrices%20for%20the%20elemental%20rotations%20about%20each%20axis%20of%20the%20%24xyz%24%20coordinate%20system%20(rotations%20of%20the%20Global%20coordinate%20system%20in%20relation%20to%20the%20local%20coordinate%20system)%20are%2C%20as%20in%20the%20two-dimensional%20case%2C%20simply%20the%20transposes%20of%20the%20matrices%20above.%0A%0A%20%20%20%20About%20the%20%24x%24%20axis%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cx%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%201%20%26%200%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%20%5Ccos%5Calpha%20%26%20%5Csin%5Calpha%20%5C%5C%0A%20%20%20%200%20%26%20-%5Csin%5Calpha%20%26%20%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20About%20the%20%24y%24%20axis%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cy%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cbeta%20%26%200%20%26%20-%5Csin%5Cbeta%20%5C%5C%0A%20%20%20%200%20%26%201%20%26%200%20%5C%5C%0A%20%20%20%20%5Csin%5Cbeta%20%26%200%20%26%20%5Ccos%5Cbeta%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20About%20the%20%24z%24%20axis%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cz%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cgamma%20%26%20%5Csin%5Cgamma%20%26%200%5C%5C%0A%20%20%20%20-%5Csin%5Cgamma%20%26%20%5Ccos%5Cgamma%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20This%20is%20equivalent%20to%20rotating%20the%20Global%20coordinate%20system%20by%20%24-%5Calpha%2C%20-%5Cbeta%2C%20-%5Cgamma%24%20in%20relation%20to%20the%20axes%20of%20the%20local%20coordinate%20system%2C%20instead%20of%20rotating%20the%20local%20coordinate%20system%20by%20%24%5Calpha%2C%20%5Cbeta%2C%20%5Cgamma%24%20in%20relation%20to%20the%20axes%20of%20the%20Global%20coordinate%20system%3B%20remember%20that%20%24%5Ccos(-%5C%3A%5Ccdot)%3D%5Ccos(%5Ccdot)%24%20and%20%24%5Csin(-%5C%3A%5Ccdot)%3D-%5Csin(%5Ccdot)%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Sequence%20of%20elemental%20rotations%0A%0A%20%20%20%20Consider%20now%20a%20sequence%20of%20elemental%20rotations%20about%20the%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Cmathbf%7BY%7D%24%20and%20%24%5Cmathbf%7BZ%7D%24%20axes%20of%20the%20fixed%20%24%5Cmathbf%7BXYZ%7D%24%20coordinate%20system%2C%20illustrated%20in%20the%20next%20figure.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-7%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Frotations_XYZ.png%3Fraw%3D1%22%20width%3D700%20alt%3D%22sequence%20of%20rotations%20about%20the%20fixed%20axes%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-7%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20Sequence%20of%20elemental%20rotations%20of%20the%20%24xyz%24%20coordinate%20system%20about%20each%20axis%2C%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Cmathbf%7BY%7D%24%2C%20%24%5Cmathbf%7BZ%7D%24%2C%20of%20the%20fixed%20%24%5Cmathbf%7BXYZ%7D%24%20coordinate%20system.%3C%2Fspan%3E%0A%0A%20%20%20%20This%20sequence%20of%20elemental%20rotations%2C%20each%20one%20of%20the%20local%20coordinate%20system%20with%20respect%20to%20the%20fixed%20Global%20coordinate%20system%2C%20is%20represented%20mathematically%20by%20a%20product%20of%20rotation%20matrices%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%2C%5C%3BXYZ%7D%7D%20%26%20%3D%20%5Cmathbf%7BR_%7BZ%7D%7D%20%5Cmathbf%7BR_%7BY%7D%7D%20%5Cmathbf%7BR_%7BX%7D%7D%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cgamma%20%26%20-%5Csin%5Cgamma%20%26%200%5C%5C%0A%20%20%20%20%5Csin%5Cgamma%20%26%20%5Ccos%5Cgamma%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cbeta%20%26%200%20%26%20%5Csin%5Cbeta%20%5C%5C%0A%20%20%20%200%20%26%201%20%26%200%20%5C%5C%0A%20%20%20%20-%5Csin%5Cbeta%20%26%200%20%26%20%5Ccos%5Cbeta%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%201%20%26%200%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%200%20%26%20%5Csin%5Calpha%20%26%20%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%26%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cbeta%5C%3A%5Ccos%5Cgamma%20%5C%3B%26%5C%3B%0A%20%20%20%20%5Csin%5Calpha%5C%3A%5Csin%5Cbeta%5C%3A%5Ccos%5Cgamma-%5Ccos%5Calpha%5C%3A%5Csin%5Cgamma%20%5C%3B%26%5C%3B%0A%20%20%20%20%5Ccos%5Calpha%5C%3A%5Csin%5Cbeta%5C%3A%5Ccos%5Cgamma%2B%5Csin%5Calpha%5C%3A%5Csin%5Cgamma%20%5C%3B%5C%3B%5C%3B%20%5C%5C%0A%20%20%20%20%5Ccos%5Cbeta%5C%3A%5Csin%5Cgamma%20%5C%3B%26%5C%3B%0A%20%20%20%20%5Csin%5Calpha%5C%3A%5Csin%5Cbeta%5C%3A%5Csin%5Cgamma%2B%5Ccos%5Calpha%5C%3A%5Ccos%5Cgamma%20%5C%3B%26%5C%3B%0A%20%20%20%20%5Ccos%5Calpha%5C%3A%5Csin%5Cbeta%5C%3A%5Csin%5Cgamma-%5Csin%5Calpha%5C%3A%5Ccos%5Cgamma%20%5C%3B%5C%3B%5C%3B%20%20%5C%5C%0A%20%20%20%20-%5Csin%5Cbeta%20%5C%3B%26%5C%3B%20%5Csin%5Calpha%5C%3A%5Ccos%5Cbeta%20%5C%3B%26%5C%3B%20%5Ccos%5Calpha%5C%3A%5Ccos%5Cbeta%20%5C%3B%5C%3B%5C%3B%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Note%20the%20order%20of%20the%20matrices%3A%20the%20first%20rotation%20is%20the%20rightmost%20one.%0A%0A%20%20%20%20We%20can%20check%20this%20matrix%20multiplication%20with%20%5BSymPy%5D(https%3A%2F%2Fwww.sympy.org)%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(sym)%3A%0A%20%20%20%20cos%2C%20sin%20%3D%20sym.cos%2C%20sym.sin%0A%20%20%20%20a%2C%20b%2C%20g%20%3D%20sym.symbols(%22alpha%2C%20beta%2C%20gamma%22)%0A%0A%20%20%20%20%23%20Elemental%20rotation%20matrices%20of%20xyz%20in%20relation%20to%20XYZ%3A%0A%20%20%20%20RX%20%3D%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20cos(a)%2C%20-sin(a)%5D%2C%20%5B0%2C%20sin(a)%2C%20cos(a)%5D%5D)%0A%20%20%20%20RY%20%3D%20sym.Matrix(%5B%5Bcos(b)%2C%200%2C%20sin(b)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B-sin(b)%2C%200%2C%20cos(b)%5D%5D)%0A%20%20%20%20RZ%20%3D%20sym.Matrix(%5B%5Bcos(g)%2C%20-sin(g)%2C%200%5D%2C%20%5Bsin(g)%2C%20cos(g)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%0A%20%20%20%20%23%20Rotation%20matrix%20of%20xyz%20in%20relation%20to%20XYZ%3A%0A%20%20%20%20RXYZ%20%3D%20RZ%20%40%20RY%20%40%20RX%0A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR_%7BGl%2C%5C%2CXYZ%7D%7D%22%2C%20RXYZ)%0A%20%20%20%20return%20RX%2C%20RXYZ%2C%20RY%2C%20RZ%2C%20a%2C%20b%2C%20cos%2C%20g%2C%20sin%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20For%20instance%2C%20here%20is%20the%20numerical%20rotation%20matrix%20for%20sequential%20elemental%20rotations%20by%20%2490%5Eo%24%20about%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Cmathbf%7BY%7D%24%20and%20%24%5Cmathbf%7BZ%7D%24%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RXYZ%2C%20a%2C%20b%2C%20g%2C%20np%2C%20sym)%3A%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b%2C%20g)%2C%20RXYZ%2C%20%22numpy%22)(np.pi%20%2F%202%2C%20np.pi%20%2F%202%2C%20np.pi%20%2F%202)%0A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR_%7BGl%2C%5C%2CXYZ%5C%2C%7D%7D(90%5Eo%2C%2090%5Eo%2C%2090%5Eo)%22%2C%20_R%2C%20digits%3D3)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Let's%20draw%20the%20rotated%20coordinate%20system%20with%20%60CCS%60.%20The%20first%20cell%20loads%20it%2C%20together%20with%20%60read_trc%60%2C%20which%20we%20will%20need%20at%20the%20end.%20In%20the%20figure%2C%20the%20black%20arrows%20are%20the%20Global%20axes%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Cmathbf%7BY%7D%24%2C%20%24%5Cmathbf%7BZ%7D%24%2C%20and%20the%20red%2C%20green%20and%20blue%20arrows%2C%20which%20%60CCS%60%20labels%20i%2C%20j%20and%20k%2C%20are%20the%20local%20axes%20%24x%24%2C%20%24y%24%2C%20%24z%24.%20Since%20the%20columns%20of%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20are%20the%20local%20versors%20written%20in%20the%20Global%20coordinate%20system%2C%20those%20are%20the%20vectors%20we%20draw.%20Use%20the%20sliders%20to%20try%20other%20angles.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20from%20notebook_resources%20import%20repo_file%0A%20%20%20%20except%20ModuleNotFoundError%20as%20_error%3A%0A%20%20%20%20%20%20%20%20if%20_error.name%20!%3D%20%22notebook_resources%22%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%0A%20%20%20%20%20%20%20%20raise%20ModuleNotFoundError(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22This%20notebook%20needs%20notebook_resources.py.%20Download%20it%20from%3A%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fraw.githubusercontent.com%2FBMClab%2FBMC%2Fmaster%2Ffunctions%2Fnotebook_resources.py%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Save%20it%20in%20the%20same%20folder%20as%20this%20notebook%2C%20then%20rerun%20this%20cell.%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22notebook_resources%22%2C%0A%20%20%20%20%20%20%20%20)%20from%20None%0A%20%20%20%20return%20(repo_file%2C)%0A%0A%0A%40app.cell%0Adef%20_(repo_file)%3A%0A%20%20%20%20import%20sys%0A%0A%20%20%20%20_functions%20%3D%20%5Brepo_file(f%22functions%2F%7B_m%7D.py%22)%20for%20_m%20in%20(%22CCS%22%2C%20%22read_trc%22)%5D%0A%20%20%20%20sys.path.insert(0%2C%20str(_functions%5B0%5D.parent))%20%20%23%20add%20to%20pythonpath%0A%20%20%20%20from%20CCS%20import%20CCS%0A%20%20%20%20from%20read_trc%20import%20read_trc%0A%0A%20%20%20%20return%20CCS%2C%20read_trc%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20alpha_XYZ%20%3D%20mo.ui.slider(start%3D-180%2C%20stop%3D180%2C%20step%3D5%2C%20value%3D90%2C%20label%3D%22%CE%B1%20about%20X%20%5Bdegrees%5D%22%2C%20show_value%3DTrue)%0A%20%20%20%20beta_XYZ%20%3D%20mo.ui.slider(start%3D-180%2C%20stop%3D180%2C%20step%3D5%2C%20value%3D90%2C%20label%3D%22%CE%B2%20about%20Y%20%5Bdegrees%5D%22%2C%20show_value%3DTrue)%0A%20%20%20%20gamma_XYZ%20%3D%20mo.ui.slider(start%3D-180%2C%20stop%3D180%2C%20step%3D5%2C%20value%3D90%2C%20label%3D%22%CE%B3%20about%20Z%20%5Bdegrees%5D%22%2C%20show_value%3DTrue)%0A%20%20%20%20mo.hstack(%5Balpha_XYZ%2C%20beta_XYZ%2C%20gamma_XYZ%5D%2C%20justify%3D%22start%22)%0A%20%20%20%20return%20alpha_XYZ%2C%20beta_XYZ%2C%20gamma_XYZ%0A%0A%0A%40app.cell%0Adef%20_(CCS%2C%20RXYZ%2C%20a%2C%20alpha_XYZ%2C%20b%2C%20beta_XYZ%2C%20g%2C%20gamma_XYZ%2C%20np%2C%20sym)%3A%0A%20%20%20%20_angles%20%3D%20np.radians(%5Balpha_XYZ.value%2C%20beta_XYZ.value%2C%20gamma_XYZ.value%5D)%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b%2C%20g)%2C%20RXYZ%2C%20%22numpy%22)(*_angles)%0A%0A%20%20%20%20%23%20the%20columns%20of%20RGl%20are%20the%20local%20versors%20in%20the%20Global%20coordinate%20system%0A%20%20%20%20_ccs%20%3D%20CCS(Oijk%3Dnp.zeros(3)%2C%20Oxyz%3Dnp.zeros(3)%2C%20ijk%3D_R.T%2C%20xyz%3Dnp.eye(3)%2C%20vector%3DFalse)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20With%20the%20sliders%20at%20their%20initial%2090%C2%B0%2C%20the%20matrix%20and%20the%20figures%20agree%3A%20the%20rotated%20%24x%24%20axis%20(first%20column%20of%20the%20matrix)%20is%20%24%5B0%2C0%2C-1%5D%24%2C%20pointing%20along%20%24-%5Cmathbf%7BZ%7D%24%3B%20the%20rotated%20%24y%24%20axis%20(second%20column)%20is%20along%20%24%5Cmathbf%7BY%7D%24%2C%20%24%5B0%2C1%2C0%5D%24%3B%20and%20the%20rotated%20%24z%24%20axis%20(third%20column)%20is%20along%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5B1%2C0%2C0%5D%24.%0A%0A%20%20%20%20We%20can%20also%20calculate%20a%20sequence%20of%20elemental%20rotations%20about%20the%20%24x%24%2C%20%24y%24%2C%20%24z%24%20axes%20of%20the%20rotating%20%24xyz%24%20coordinate%20system%2C%20illustrated%20in%20the%20next%20figure.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-8%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Frotations_xyz2.png%3Fraw%3D1%22%20width%3D700%20alt%3D%22sequence%20of%20rotations%20about%20the%20local%20axes%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-8%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20Sequence%20of%20elemental%20rotations%20of%20a%20second%20%24xyz%24%20local%20coordinate%20system%20about%20each%20axis%2C%20%24x%24%2C%20%24y%24%2C%20%24z%24%2C%20of%20the%20rotating%20%24xyz%24%20coordinate%20system.%3C%2Fspan%3E%0A%0A%20%20%20%20Likewise%2C%20this%20sequence%20of%20elemental%20rotations%2C%20each%20one%20of%20the%20local%20coordinate%20system%20with%20respect%20to%20the%20rotating%20local%20coordinate%20system%2C%20is%20represented%20by%20a%20product%20of%20rotation%20matrices%2C%20which%20are%20the%20inverses%20of%20the%20matrices%20for%20the%20rotations%20about%20%24%5Cmathbf%7BX%2CY%2CZ%7D%24%2C%20as%20we%20saw%20earlier%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxyz%7D%20%26%20%3D%20%5Cmathbf%7BR_%7Bz%7D%7D%20%5Cmathbf%7BR_%7By%7D%7D%20%5Cmathbf%7BR_%7Bx%7D%7D%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cgamma%20%26%20%5Csin%5Cgamma%20%26%200%5C%5C%0A%20%20%20%20-%5Csin%5Cgamma%20%26%20%5Ccos%5Cgamma%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cbeta%20%26%200%20%26%20-%5Csin%5Cbeta%20%5C%5C%0A%20%20%20%200%20%26%201%20%26%200%20%5C%5C%0A%20%20%20%20%5Csin%5Cbeta%20%26%200%20%26%20%5Ccos%5Cbeta%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%201%20%26%200%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%20%5Ccos%5Calpha%20%26%20%5Csin%5Calpha%20%5C%5C%0A%20%20%20%200%20%26%20-%5Csin%5Calpha%20%26%20%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%26%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cbeta%5C%3A%5Ccos%5Cgamma%20%5C%3B%26%5C%3B%0A%20%20%20%20%5Csin%5Calpha%5C%3A%5Csin%5Cbeta%5C%3A%5Ccos%5Cgamma%2B%5Ccos%5Calpha%5C%3A%5Csin%5Cgamma%20%5C%3B%26%5C%3B%0A%20%20%20%20-%5Ccos%5Calpha%5C%3A%5Csin%5Cbeta%5C%3A%5Ccos%5Cgamma%2B%5Csin%5Calpha%5C%3A%5Csin%5Cgamma%20%5C%3B%5C%3B%5C%3B%20%5C%5C%0A%20%20%20%20-%5Ccos%5Cbeta%5C%3A%5Csin%5Cgamma%20%5C%3B%26%5C%3B%0A%20%20%20%20-%5Csin%5Calpha%5C%3A%5Csin%5Cbeta%5C%3A%5Csin%5Cgamma%2B%5Ccos%5Calpha%5C%3A%5Ccos%5Cgamma%20%5C%3B%26%5C%3B%0A%20%20%20%20%5Ccos%5Calpha%5C%3A%5Csin%5Cbeta%5C%3A%5Csin%5Cgamma%2B%5Csin%5Calpha%5C%3A%5Ccos%5Cgamma%20%5C%3B%5C%3B%5C%3B%20%20%5C%5C%0A%20%20%20%20%5Csin%5Cbeta%20%5C%3B%26%5C%3B%20-%5Csin%5Calpha%5C%3A%5Ccos%5Cbeta%20%5C%3B%26%5C%3B%20%5Ccos%5Calpha%5C%3A%5Ccos%5Cbeta%20%5C%3B%5C%3B%5C%3B%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20As%20before%2C%20the%20order%20of%20the%20matrices%20is%20from%20right%20to%20left.%0A%0A%20%20%20%20Once%20again%2C%20we%20can%20check%20this%20matrix%20multiplication%20with%20SymPy%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(a%2C%20b%2C%20cos%2C%20g%2C%20sin%2C%20sym)%3A%0A%20%20%20%20%23%20Elemental%20rotation%20matrices%20of%20xyz%20(local)%3A%0A%20%20%20%20Rx%20%3D%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20cos(a)%2C%20sin(a)%5D%2C%20%5B0%2C%20-sin(a)%2C%20cos(a)%5D%5D)%0A%20%20%20%20Ry%20%3D%20sym.Matrix(%5B%5Bcos(b)%2C%200%2C%20-sin(b)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5Bsin(b)%2C%200%2C%20cos(b)%5D%5D)%0A%20%20%20%20Rz%20%3D%20sym.Matrix(%5B%5Bcos(g)%2C%20sin(g)%2C%200%5D%2C%20%5B-sin(g)%2C%20cos(g)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%0A%20%20%20%20%23%20Rotation%20matrix%20of%20xyz'%20in%20relation%20to%20xyz%3A%0A%20%20%20%20Rxyz%20%3D%20Rz%20%40%20Ry%20%40%20Rx%0A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxyz%7D%22%2C%20Rxyz)%0A%20%20%20%20return%20Rx%2C%20Rxyz%2C%20Ry%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20For%20instance%2C%20the%20numerical%20rotation%20matrix%20for%20sequential%20elemental%20rotations%20by%20%2490%5Eo%24%20about%20%24x%24%2C%20%24y%24%2C%20%24z%24%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Rxyz%2C%20a%2C%20b%2C%20g%2C%20np%2C%20sym)%3A%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b%2C%20g)%2C%20Rxyz%2C%20%22numpy%22)(np.pi%20%2F%202%2C%20np.pi%20%2F%202%2C%20np.pi%20%2F%202)%0A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxyz%5C%2C%7D(90%5Eo%2C%2090%5Eo%2C%2090%5Eo)%22%2C%20_R%2C%20digits%3D3)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Let's%20compare%20this%20matrix%20with%20the%20figure.%20Remember%20that%20it%20is%20the%20Global-to-local%20rotation%20matrix%2C%20%24%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxyz%7D%24%2C%20in%20which%20the%20coordinates%20of%20the%20local%20versors%20are%20the%20*rows*%2C%20not%20the%20columns.%20With%20this%20in%20mind%2C%20the%20figure%20and%20the%20matrix%20agree%3A%20the%20rotated%20%24x%24%20axis%20(first%20row)%20is%20along%20%24%5Cmathbf%7BZ%7D%24%2C%20%24%5B0%2C0%2C1%5D%24%3B%20the%20rotated%20%24y%24%20axis%20(second%20row)%20is%20along%20%24-%5Cmathbf%7BY%7D%24%2C%20%24%5B0%2C-1%2C0%5D%24%3B%20and%20the%20rotated%20%24z%24%20axis%20(third%20row)%20is%20along%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5B1%2C0%2C0%5D%24.%0A%0A%20%20%20%20In%20fact%2C%20this%20example%20cannot%20tell%20rows%20from%20columns%2C%20because%20the%20matrix%20above%20is%20symmetric.%20Let's%20look%20at%20the%20matrix%20after%20only%20the%20first%20two%20rotations%2C%20%24%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxy%7D%24%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Rx%2C%20Ry%2C%20a%2C%20b%2C%20np%2C%20sym)%3A%0A%20%20%20%20_Rxy%20%3D%20Ry%20*%20Rx%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b)%2C%20_Rxy%2C%20%22numpy%22)(np.pi%20%2F%202%2C%20np.pi%20%2F%202)%0A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxy%5C%2C%7D(90%5Eo%2C%2090%5Eo)%22%2C%20_R%2C%20digits%3D3)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20In%20the%20third%20plot%20of%20the%20figure%2C%20the%20versor%20%24x%24%20is%20along%20the%20Global%20axis%20%24%5Cmathbf%7BY%7D%24%2C%20so%20its%20coordinates%20in%20the%20Global%20coordinate%20system%20are%20%24%5B0%2C1%2C0%5D%24%2C%20and%20that%20is%20indeed%20the%20first%20*row*%20of%20the%20matrix.%20Check%20the%20other%20two%20rows.%0A%0A%20%20%20%20What%2C%20then%2C%20are%20the%20columns%20of%20this%20matrix%3F%20The%20coordinates%20of%20the%20Global%20versors%20in%20the%20local%20coordinate%20system.%20The%20first%20column%20is%20the%20coordinates%20of%20%24%5Cmathbf%7BX%7D%24%2C%20which%20is%20aligned%20with%20%24z%24%3A%20%24%5B0%2C0%2C1%5D%24.%0A%0A%20%20%20%20Here%2C%20too%2C%20you%20can%20try%20other%20angles.%20This%20time%20the%20local%20versors%20are%20the%20rows%20of%20the%20matrix%2C%20so%20they%20are%20what%20we%20pass%20to%20%60CCS%60%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20alpha_xyz%20%3D%20mo.ui.slider(start%3D-180%2C%20stop%3D180%2C%20step%3D5%2C%20value%3D60%2C%20label%3D%22%CE%B1%20about%20x%20%5Bdegrees%5D%22%2C%20show_value%3DTrue)%0A%20%20%20%20beta_xyz%20%3D%20mo.ui.slider(start%3D-180%2C%20stop%3D180%2C%20step%3D5%2C%20value%3D45%2C%20label%3D%22%CE%B2%20about%20y%20%5Bdegrees%5D%22%2C%20show_value%3DTrue)%0A%20%20%20%20gamma_xyz%20%3D%20mo.ui.slider(start%3D-180%2C%20stop%3D180%2C%20step%3D5%2C%20value%3D30%2C%20label%3D%22%CE%B3%20about%20z%20%5Bdegrees%5D%22%2C%20show_value%3DTrue)%0A%20%20%20%20mo.hstack(%5Balpha_xyz%2C%20beta_xyz%2C%20gamma_xyz%5D%2C%20justify%3D%22start%22)%0A%20%20%20%20return%20alpha_xyz%2C%20beta_xyz%2C%20gamma_xyz%0A%0A%0A%40app.cell%0Adef%20_(CCS%2C%20Rxyz%2C%20a%2C%20alpha_xyz%2C%20b%2C%20beta_xyz%2C%20g%2C%20gamma_xyz%2C%20np%2C%20sym)%3A%0A%20%20%20%20_angles%20%3D%20np.radians(%5Balpha_xyz.value%2C%20beta_xyz.value%2C%20gamma_xyz.value%5D)%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b%2C%20g)%2C%20Rxyz%2C%20%22numpy%22)(*_angles)%0A%0A%20%20%20%20%23%20the%20rows%20of%20RlG%20are%20the%20local%20versors%20in%20the%20Global%20coordinate%20system%0A%20%20%20%20_ccs%20%3D%20CCS(Oijk%3Dnp.zeros(3)%2C%20Oxyz%3Dnp.zeros(3)%2C%20ijk%3D_R%2C%20xyz%3Dnp.eye(3)%2C%20vector%3DFalse)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20A%20rotation%20in%20one%20coordinate%20system%20is%20a%20negative%20rotation%20in%20the%20other%0A%0A%20%20%20%20We%20saw%20for%20the%20elemental%20rotations%20that%20rotating%20the%20local%20coordinate%20system%2C%20%24xyz%24%2C%20by%20%24%5Calpha%2C%20%5Cbeta%2C%20%5Cgamma%24%20in%20relation%20to%20the%20axes%20of%20the%20Global%20coordinate%20system%20is%20equivalent%20to%20rotating%20the%20Global%20coordinate%20system%2C%20%24%5Cmathbf%7BXYZ%7D%24%2C%20by%20%24-%5Calpha%2C%20-%5Cbeta%2C%20-%5Cgamma%24%20in%20relation%20to%20the%20axes%20of%20the%20local%20coordinate%20system.%20The%20same%20property%20applies%20to%20a%20sequence%20of%20rotations%3A%20rotations%20of%20%24xyz%24%20in%20relation%20to%20%24%5Cmathbf%7BXYZ%7D%24%20by%20%24%5Calpha%2C%20%5Cbeta%2C%20%5Cgamma%24%20result%20in%20the%20same%20matrix%20as%20rotations%20of%20%24%5Cmathbf%7BXYZ%7D%24%20in%20relation%20to%20%24xyz%24%20by%20%24-%5Calpha%2C%20-%5Cbeta%2C%20-%5Cgamma%24%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%2C%5C%2CXYZ%5C%2C%7D%7D(%5Calpha%2C%5Cbeta%2C%5Cgamma)%20%26%20%3D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CZ%7D%7D(%5Cgamma)%5C%2C%20%5Cmathbf%7BR_%7BGl%2C%5C%2CY%7D%7D(%5Cbeta)%5C%2C%20%5Cmathbf%7BR_%7BGl%2C%5C%2CX%7D%7D(%5Calpha)%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cz%5C%2C%7D(-%5Cgamma)%5C%2C%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cy%5C%2C%7D(-%5Cbeta)%5C%2C%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cx%5C%2C%7D(-%5Calpha)%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxyz%5C%2C%7D(-%5Calpha%2C-%5Cbeta%2C-%5Cgamma)%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Compare%20the%20%24%5Cmathbf%7BR_%7BGl%2C%5C%2CXYZ%7D%7D%24%20and%20%24%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxyz%7D%24%20matrices%20above%20to%20confirm%20it%2C%20or%20let%20SymPy%20do%20it%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RXYZ%2C%20a%2C%20b%2C%20cos%2C%20g%2C%20sin%2C%20sym)%3A%0A%20%20%20%20%23%20Elemental%20rotation%20matrices%20of%20XYZ%20in%20relation%20to%20xyz%2C%20with%20all%20angles%20negated%3A%0A%20%20%20%20_Rx_neg%20%3D%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20cos(-a)%2C%20-sin(-a)%5D%2C%20%5B0%2C%20sin(-a)%2C%20cos(-a)%5D%5D).T%0A%20%20%20%20_Ry_neg%20%3D%20sym.Matrix(%5B%5Bcos(-b)%2C%200%2C%20sin(-b)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B-sin(-b)%2C%200%2C%20cos(-b)%5D%5D).T%0A%20%20%20%20_Rz_neg%20%3D%20sym.Matrix(%5B%5Bcos(-g)%2C%20-sin(-g)%2C%200%5D%2C%20%5Bsin(-g)%2C%20cos(-g)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D).T%0A%0A%20%20%20%20%23%20Rotation%20matrix%20of%20XYZ%20in%20relation%20to%20xyz%3A%0A%20%20%20%20_Rxyz_neg%20%3D%20_Rz_neg%20*%20_Ry_neg%20*%20_Rx_neg%0A%0A%20%20%20%20print(%22RGl%2CXYZ(alpha%2C%20beta%2C%20gamma)%20%3D%3D%20RlG%2Cxyz(-alpha%2C%20-beta%2C%20-gamma)%3A%22%2C%20RXYZ%20%3D%3D%20_Rxyz_neg)%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxyz%5C%2C%7D(-%5Calpha%2C-%5Cbeta%2C-%5Cgamma)%22%2C%20_Rxyz_neg)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20A%20rotation%20in%20one%20coordinate%20system%20is%20the%20transpose%20of%20the%20inverse%20sequence%20in%20the%20other%0A%0A%20%20%20%20There%20is%20another%20property%20relating%20the%20two%20kinds%20of%20rotation%20matrix.%20The%20Global-to-local%20rotation%20matrix%20for%2C%20say%2C%20the%20%24xyz%24%20sequence%20is%20the%20transpose%20of%20the%20rotation%20matrix%20for%20the%20inverse%20operation%20(from%20local%20to%20Global)%20with%20the%20inverse%20sequence%20(%24%5Cmathbf%7BZYX%7D%24)%2C%20and%20vice%20versa%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cxyz%7D(%5Calpha%2C%5Cbeta%2C%5Cgamma)%20%26%20%3D%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cz%5C%2C%7D%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cy%5C%2C%7D%20%5Cmathbf%7BR%7D_%7B%5Cmathbf%7BlG%7D%2C%5C%2Cx%7D%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CZ%5C%2C%7D%5E%7B-1%7D%7D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CY%5C%2C%7D%5E%7B-1%7D%7D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CX%5C%2C%7D%5E%7B-1%7D%7D%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CZ%5C%2C%7D%5E%7BT%7D%7D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CY%5C%2C%7D%5E%7BT%7D%7D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CX%5C%2C%7D%5E%7BT%7D%7D%20%5C%5C%0A%20%20%20%20%26%20%3D%20(%5Cmathbf%7BR_%7BGl%2C%5C%2CX%5C%2C%7D%7D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CY%5C%2C%7D%7D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CZ%7D%7D)%5E%5Cmathbf%7BT%7D%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cmathbf%7BR_%7BGl%2C%5C%2CZYX%5C%2C%7D%5E%7BT%7D%7D(%5Cgamma%2C%5Cbeta%2C%5Calpha)%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20where%20we%20used%20two%20properties%3A%20the%20inverse%20of%20a%20rotation%20matrix%20(which%20is%20orthonormal)%20is%20its%20transpose%2C%20and%20the%20transpose%20of%20a%20product%20of%20matrices%20is%20the%20product%20of%20their%20transposes%20in%20reverse%20order.%20This%20is%20what%20the%20figure%20of%20the%20book%20showed%3A%20rotating%20about%20the%20rotating%20axes%20in%20one%20order%20ends%20where%20rotating%20about%20the%20fixed%20axes%20in%20the%20opposite%20order%20does.%0A%0A%20%20%20%20Let's%20verify%20this%20property%20with%20SymPy%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RX%2C%20RY%2C%20RZ%2C%20Rxyz)%3A%0A%20%20%20%20RZYX%20%3D%20RX%20*%20RY%20*%20RZ%0A%0A%20%20%20%20print(%22RlG%2Cxyz(alpha%2C%20beta%2C%20gamma)%20%3D%3D%20RGl%2CZYX(gamma%2C%20beta%2C%20alpha)%5ET%3A%22%2C%20Rxyz%20%3D%3D%20RZYX.T)%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR_%7BGl%2C%5C%2CZYX%5C%2C%7D%5ET%7D%22%2C%20RZYX.T)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Guiding%20questions%201.**%0A%0A%20%20%20%201.%20A%20rotation%20matrix%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20has%20the%20local%20versors%20as%20its%20columns.%20Without%20computing%20anything%2C%20what%20are%20the%20columns%20of%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%3F%0A%20%20%20%202.%20Why%20does%20the%20first%20rotation%20of%20a%20sequence%20appear%20as%20the%20*rightmost*%20matrix%20of%20the%20product%3F%0A%20%20%20%203.%20Look%20again%20at%20the%20two%20orders%20in%20the%20first%20row%20of%20the%20figure%20of%20the%20book.%20Using%20the%20property%20above%2C%20which%20sequence%20about%20the%20rotating%20axes%20gives%20the%20same%20final%20orientation%20as%20each%20of%20them%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Sequence%20of%20rotations%20of%20a%20vector%0A%0A%20%20%20%20We%20saw%20in%20%5BRigid-body%20transformations%20in%20a%20plane%20(2D)%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_2d.py)%20that%20the%20rotation%20matrix%20can%20also%20be%20used%20to%20rotate%20a%20vector%20(or%20a%20point%2C%20an%20image%2C%20a%20solid)%20by%20a%20given%20angle%20about%20an%20axis%20of%20the%20coordinate%20system.%20Let's%20investigate%20that%20in%203D%20with%20the%20book%2C%20rotated%20in%20different%20orders%20about%20the%20Global%20and%20local%20coordinate%20systems.%0A%0A%20%20%20%20Before%20any%20rotation%2C%20the%20point%20drawn%20in%20that%20figure%20as%20a%20round%20black%20dot%20on%20the%20spine%20of%20the%20book%20has%20coordinates%20%24%5Cmathbf%7BP%7D%3D%5B0%2C%201%2C%202%5D%24%20(the%20book%20has%20thickness%200%2C%20width%201%20and%20height%202).%0A%0A%20%20%20%20After%20the%20first%20sequence%20of%20rotations%20in%20the%20figure%20(about%20%24%5Cmathbf%7BX%7D%24%20and%20then%20%24%5Cmathbf%7BY%7D%24%2C%20by%20%2490%5Eo%24%20each%20time)%2C%20%24%5Cmathbf%7BP%7D%24%20has%20coordinates%20%24%5Cmathbf%7BP_1%7D%3D%5B1%2C%20-2%2C%200%5D%24%20in%20the%20Global%20coordinate%20system.%20Let's%20verify%20that%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RX%2C%20RY%2C%20a%2C%20b%2C%20np%2C%20sym)%3A%0A%20%20%20%20P%20%3D%20np.array(%5B%5B0%2C%201%2C%202%5D%5D).T%0A%0A%20%20%20%20_RXY%20%3D%20RY%20*%20RX%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b)%2C%20_RXY%2C%20%22numpy%22)(np.pi%20%2F%202%2C%20np.pi%20%2F%202)%0A%20%20%20%20_P1%20%3D%20np.dot(_R%2C%20P)%0A%0A%20%20%20%20print(%22P1%20%3D%22%2C%20_P1.T.round(4)%20%2B%200.0)%0A%20%20%20%20return%20(P%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20As%20expected.%0A%0A%20%20%20%20Although%20we%20are%20rotating%20a%20vector%20here%2C%20without%20any%20need%20for%20the%20idea%20of%20a%20transformation%20between%20coordinate%20systems%2C%20we%20used%20the%20local-to-Global%20rotation%20matrix%2C%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24.%20As%20we%20saw%20for%20the%202D%20case%2C%20this%20matrix%20performs%20a%20counterclockwise%20(positive)%20rotation.%20To%20rotate%20the%20vector%20clockwise%20(negative%20direction)%2C%20we%20can%20use%20the%20very%20same%20matrix%20with%20a%20negative%20angle%2C%20or%20the%20inverse%20matrix%2C%20the%20Global-to-local%20rotation%20matrix%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%2C%20with%20a%20positive%20angle%2C%20because%20%24%5Cmathbf%7BR_%7BGl%7D%7D(%5Calpha)%20%3D%20%5Cmathbf%7BR_%7BlG%7D%7D(-%5Calpha)%24.%20Bear%20in%20mind%20that%20even%20in%20the%20latter%20case%20we%20are%20rotating%20about%20the%20Global%20coordinate%20system.%0A%0A%20%20%20%20Now%20let's%20deduce%20algebraically%20the%20position%20of%20the%20point%20%24%5Cmathbf%7BP%7D%24%20after%20the%20rotations%20about%20the%20*local*%20coordinate%20system%2C%20the%20second%20row%20of%20the%20figure.%20The%20point%20starts%20at%20the%20same%20position%2C%20%24%5Cmathbf%7BP%7D%3D%5B0%2C%201%2C%202%5D%24%2C%20and%20the%20book%20is%20rotated%20about%20%24x%24%20and%20then%20about%20%24y%24%2C%20by%20%2490%5Eo%24%20each%20time.%20Where%20is%20the%20point%20now%3F%0A%0A%20%20%20%20The%20question%20implicitly%20asks%20for%20the%20position%20in%20the%20Global%20coordinate%20system%2C%20because%20the%20local%20coordinate%20system%20rotates%20with%20the%20book%20and%20the%20point%20never%20moves%20in%20it.%20By%20inspection%20of%20the%20figure%2C%20the%20new%20position%20is%20%24%5Cmathbf%7BP_1%7D%3D%5B2%2C%200%2C%201%5D%24.%20Let's%20naively%20try%20to%20obtain%20it%20by%20repeating%20the%20steps%20above%20with%20the%20local%20matrices%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(P%2C%20Rx%2C%20Ry%2C%20a%2C%20b%2C%20np%2C%20sym)%3A%0A%20%20%20%20_Rxy%20%3D%20Ry%20*%20Rx%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b)%2C%20_Rxy%2C%20%22numpy%22)(np.pi%20%2F%202%2C%20np.pi%20%2F%202)%0A%20%20%20%20_P1%20%3D%20np.dot(_R%2C%20P)%0A%0A%20%20%20%20print(%22P1%20%3D%22%2C%20_P1.T.round(4)%20%2B%200.0)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20wrong%20answer.%0A%0A%20%20%20%20The%20problem%20is%20that%20we%20defined%20the%20rotation%20of%20a%20vector%20with%20the%20local-to-Global%20rotation%20matrix.%20One%20correct%20solution%20is%20to%20keep%20multiplying%20the%20Global-to-local%20rotation%20matrices%2C%20%24%5Cmathbf%7BR%7D_%7Bxy%7D%20%3D%20%5Cmathbf%7BR%7D_y%5C%2C%5Cmathbf%7BR%7D_x%24%2C%20transpose%20%24%5Cmathbf%7BR%7D_%7Bxy%7D%24%20to%20obtain%20the%20corresponding%20local-to-Global%20rotation%20matrix%2C%20%24%5Cmathbf%7BR_%7BXY%7D%7D%3D%5Cmathbf%7BR%5ET%7D_%7Bxy%7D%24%2C%20and%20then%20rotate%20the%20vector%20with%20this%20matrix%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(P%2C%20Rx%2C%20Ry%2C%20a%2C%20b%2C%20np%2C%20sym)%3A%0A%20%20%20%20_Rxy%20%3D%20Ry%20*%20Rx%0A%20%20%20%20_RXY%20%3D%20_Rxy.T%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b)%2C%20_RXY%2C%20%22numpy%22)(np.pi%20%2F%202%2C%20np.pi%20%2F%202)%0A%20%20%20%20_P1%20%3D%20np.dot(_R%2C%20P)%0A%0A%20%20%20%20print(%22P1%20%3D%22%2C%20_P1.T.round(4)%20%2B%200.0)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20correct%20answer.%0A%0A%20%20%20%20Another%20solution%20is%20to%20understand%20that%2C%20with%20the%20Global-to-local%20rotation%20matrix%2C%20counterclockwise%20rotations%20(as%20performed%20with%20the%20book%20in%20the%20figure)%20are%20negative%2C%20not%20positive%2C%20and%20that%20the%20order%20of%20the%20matrix%20multiplication%20is%20inverted%3A%20it%20should%20be%20%24%5Cmathbf%7BR%5C_%7D_%7Bxyz%7D%20%3D%20%5Cmathbf%7BR%7D_x%5C%2C%5Cmathbf%7BR%7D_y%5C%2C%5Cmathbf%7BR%7D_z%24%20(the%20underscore%20is%20a%20reminder%20that%20this%20is%20not%20the%20convention%20adopted%20here).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(P%2C%20Rx%2C%20Ry%2C%20a%2C%20b%2C%20np%2C%20sym)%3A%0A%20%20%20%20_R_xy%20%3D%20Rx%20*%20Ry%0A%20%20%20%20_R%20%3D%20sym.lambdify((a%2C%20b)%2C%20_R_xy%2C%20%22numpy%22)(-np.pi%20%2F%202%2C%20-np.pi%20%2F%202)%0A%20%20%20%20_P1%20%3D%20np.dot(_R%2C%20P)%0A%0A%20%20%20%20print(%22P1%20%3D%22%2C%20_P1.T.round(4)%20%2B%200.0)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20correct%20answer%20again.%0A%0A%20%20%20%20You%20will%20find%20texts%20on%203D%20rotations%20that%20adopt%20this%20latter%20convention%20as%20the%20standard%3A%20they%20introduce%20the%20Global-to-local%20rotation%20matrix%20and%20describe%20a%20sequence%20of%20rotations%20as%20a%20matrix%20product%20in%20the%20direct%20order%2C%20%24%5Cmathbf%7BR%5C_%7D_%7Bxyz%7D%20%3D%20%5Cmathbf%7BR%7D_x%5C%2C%5Cmathbf%7BR%7D_y%5C%2C%5Cmathbf%7BR%7D_z%24%2C%20the%20opposite%20of%20what%20we%20do%20here.%20It%20is%20a%20matter%20of%20convention%2C%20nothing%20more%2C%20but%20you%20have%20to%20know%20which%20convention%20a%20text%2C%20a%20paper%20or%20a%20piece%20of%20software%20is%20using.%0A%0A%20%20%20%20**Challenge%201.**%20Deduce%20the%20position%20of%20the%20point%20%24%5Cmathbf%7BP%7D%24%20after%20the%20inverse%20order%20of%20rotations%2C%20first%20about%20the%20Global%20coordinate%20system%20and%20then%20about%20the%20local%20one%2C%20by%20inspection%20of%20the%20figure.%20Then%20check%20your%20answers%20with%20code.%20Which%20of%20the%20four%20results%20coincide%2C%20and%20why%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Codman's%20paradox%2C%20computed%0A%0A%20%20%20%20We%20now%20have%20everything%20needed%20to%20explain%20the%20arm%20movements%20at%20the%20start%20of%20this%20notebook.%20Let's%20use%20a%20Global%20coordinate%20system%20with%20%24%5Cmathbf%7BX%7D%24%20pointing%20forward%2C%20%24%5Cmathbf%7BY%7D%24%20upwards%20and%20%24%5Cmathbf%7BZ%7D%24%20to%20the%20right%2C%20the%20convention%20recommended%20for%20motion%20analysis%20by%20the%20International%20Society%20of%20Biomechanics%20(Wu%20%26%20Cavanagh%2C%201995).%20We%20follow%20two%20vectors%20attached%20to%20the%20right%20arm%3A%20its%20long%20axis%2C%20pointing%20from%20the%20shoulder%20down%20to%20the%20hand%2C%20%24%5B0%2C%20-1%2C%200%5D%24%3B%20and%20the%20direction%20the%20palm%20faces%2C%20initially%20towards%20the%20thigh%2C%20%24%5B0%2C%200%2C%20-1%5D%24.%0A%0A%20%20%20%20The%20three%20movements%20are%20rotations%20about%20fixed%20axes%3A%0A%0A%20%20%20%201.%20Flexion%3A%20the%20arm%20swings%20forward%20and%20up%2C%20a%20rotation%20of%20%24%2B90%5Eo%24%20about%20%24%5Cmathbf%7BZ%7D%24.%0A%20%20%20%202.%20Horizontal%20abduction%3A%20the%20arm%20swings%20from%20the%20front%20to%20the%20side%2C%20a%20rotation%20of%20%24-90%5Eo%24%20about%20%24%5Cmathbf%7BY%7D%24.%0A%20%20%20%203.%20Adduction%3A%20the%20arm%20comes%20down%20from%20the%20side%2C%20a%20rotation%20of%20%24%2B90%5Eo%24%20about%20%24%5Cmathbf%7BX%7D%24.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20check%20those%20signs%20with%20the%20right-hand%20rule%2C%20and%20predict%20where%20the%20palm%20faces%20at%20the%20end.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_arm%20%3D%20np.array(%5B0%2C%20-1%2C%200%5D)%20%20%23%20long%20axis%20of%20the%20arm%2C%20from%20the%20shoulder%20to%20the%20hand%0A%20%20%20%20_palm%20%3D%20np.array(%5B0%2C%200%2C%20-1%5D)%20%20%23%20the%20right%20palm%2C%20facing%20the%20thigh%0A%20%20%20%20_steps%20%3D%20%5B%0A%20%20%20%20%20%20%20%20(%22flexion%2C%20%2B90%20about%20Z%22%2C%20rotZ(90))%2C%0A%20%20%20%20%20%20%20%20(%22horizontal%20abduction%2C%20-90%20about%20Y%22%2C%20rotY(-90))%2C%0A%20%20%20%20%20%20%20%20(%22adduction%2C%20%2B90%20about%20X%22%2C%20rotX(90))%2C%0A%20%20%20%20%5D%0A%0A%20%20%20%20_R%20%3D%20np.eye(3)%0A%20%20%20%20for%20_name%2C%20_Ri%20in%20_steps%3A%0A%20%20%20%20%20%20%20%20_R%20%3D%20_Ri%20%40%20_R%20%20%23%20each%20new%20rotation%20about%20a%20fixed%20axis%20multiplies%20from%20the%20left%0A%20%20%20%20%20%20%20%20print(f%22after%20%7B_name%3A34s%7D%20arm%3A%20%7B(_R%20%40%20_arm).round(4)%20%2B%200.0%7D%20%20palm%3A%20%7B(_R%20%40%20_palm).round(4)%20%2B%200.0%7D%22)%0A%0A%20%20%20%20print(%22%5CnRotation%20matrix%20of%20the%20whole%20sequence%3A%5Cn%22%2C%20_R.round(4)%20%2B%200.0)%0A%20%20%20%20print(%22%5CnIs%20it%20a%20single%20rotation%20of%20-90%20degrees%20about%20Y%3F%22%2C%20np.allclose(_R%2C%20rotY(-90)))%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20arm%20comes%20back%20to%20%24%5B0%2C-1%2C0%5D%24%2C%20hanging%20at%20the%20side%2C%20but%20the%20palm%2C%20which%20started%20facing%20the%20thigh%2C%20now%20faces%20forward%2C%20%24%5B1%2C0%2C0%5D%24.%20And%20the%20product%20of%20the%20three%20matrices%20is%20a%20single%20rotation%20of%20%24-90%5Eo%24%20about%20the%20vertical%20axis%2C%20which%20at%20the%20end%20is%20also%20the%20long%20axis%20of%20the%20arm%3A%20the%20arm%20has%20rotated%20externally%20by%2090%C2%B0%2C%20without%20a%20single%20movement%20about%20its%20long%20axis.%0A%0A%20%20%20%20There%20is%20no%20contradiction.%20Each%20movement%20was%20a%20rotation%20about%20an%20axis%20perpendicular%20to%20the%20arm%20*at%20that%20moment*%2C%20but%20those%20axes%20were%20fixed%20in%20space%20while%20the%20arm%20moved%2C%20and%20three%20rotations%20compose%20into%20a%20rotation%20about%20an%20axis%20that%20none%20of%20them%20used.%20In%20a%20plane%20that%20cannot%20happen%3A%20rotations%20about%20the%20one%20available%20axis%20simply%20add.%20In%20three%20dimensions%2C%20the%20result%20of%20a%20sequence%20of%20rotations%20is%20the%20product%20of%20the%20matrices%2C%20not%20the%20sum%20of%20the%20angles.%0A%0A%20%20%20%20For%20the%20shoulder%2C%20this%20is%20not%20a%20curiosity.%20It%20means%20that%20the%20axial%20rotation%20of%20the%20humerus%20depends%20on%20the%20path%20the%20arm%20took%20to%20reach%20a%20position%2C%20and%20that%20a%20description%20of%20the%20arm's%20orientation%20by%20three%20angles%20depends%20on%20the%20order%20in%20which%20the%20angles%20are%20defined.%0A%0A%20%20%20%20**Guiding%20questions%202.**%0A%0A%20%20%20%201.%20Problem%206%20asks%20you%20to%20compute%20the%20order%20you%20tried%20in%20Guiding%20question%200.2.%20Before%20computing%2C%20predict%3A%20will%20the%20palm%20end%20up%20facing%20forward%20again%3F%0A%20%20%20%202.%20Why%20did%20the%20second%20movement%20change%20the%20direction%20of%20the%20palm%2C%20while%20the%20first%20one%20did%20not%3F%0A%20%20%20%203.%20A%20colleague%20reports%20the%20arm's%20orientation%20as%20the%20sum%20of%20the%20three%20angles%20about%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Cmathbf%7BY%7D%24%20and%20%24%5Cmathbf%7BZ%7D%24.%20What%20would%20that%20sum%20be%20for%20Codman's%20movement%2C%20and%20what%20is%20wrong%20with%20it%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20One%20rotation%20is%20enough%0A%0A%20%20%20%20Codman's%20three%20rotations%20turned%20out%20to%20be%20a%20single%20rotation%20about%20one%20axis.%20That%20is%20not%20a%20coincidence%20of%20the%20example.%20Euler's%20rotation%20theorem%20says%20that%20*any*%20rotation%20matrix%20is%20a%20single%20rotation%2C%20by%20some%20angle%20%24%5Ctheta%24%2C%20about%20some%20axis%20%24%5Chat%7B%5Cmathbf%7Bn%7D%7D%24.%20Both%20can%20be%20read%20off%20the%20matrix.%20The%20trace%20(the%20sum%20of%20the%20diagonal)%20gives%20the%20angle%2C%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathrm%7Btr%7D(%5Cmathbf%7BR%7D)%20%3D%201%20%2B%202%5Ccos%5Ctheta%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20the%20antisymmetric%20part%20of%20the%20matrix%20gives%20the%20axis%2C%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%20R_%7B21%7D%20-%20R_%7B12%7D%20%5C%5C%20R_%7B02%7D%20-%20R_%7B20%7D%20%5C%5C%20R_%7B10%7D%20-%20R_%7B01%7D%20%5Cend%7Bbmatrix%7D%20%3D%202%5Csin%5Ctheta%5C%3B%5Chat%7B%5Cmathbf%7Bn%7D%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20(rows%20and%20columns%20numbered%20from%200%2C%20as%20in%20Python).%20The%20formula%20for%20the%20axis%20fails%20in%20two%20cases%3A%20with%20no%20rotation%2C%20where%20any%20axis%20will%20do%2C%20and%20for%20a%20half%20turn%2C%20where%20%24%5Csin%5Ctheta%20%3D%200%24%3B%20for%20the%20half%20turn%2C%20%24(%5Cmathbf%7BR%7D%20%2B%20%5Cmathbf%7BI%7D)%2F2%20%3D%20%5Chat%7B%5Cmathbf%7Bn%7D%7D%5Chat%7B%5Cmathbf%7Bn%7D%7D%5ET%24%20gives%20the%20axis%20instead.%20Here%20is%20a%20function%20that%20handles%20all%20three%20cases%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20axis_angle(R)%3A%0A%20%20%20%20%22%22%22Axis%20(versor)%20and%20angle%20(degrees%2C%20from%200%20to%20180)%20of%20the%20single%20rotation%20equivalent%20to%20R.%0A%0A%20%20%20%20R%20is%20a%20local-to-Global%20rotation%20matrix%20(or%20a%20rotation%20of%20vectors).%20With%20no%0A%20%20%20%20rotation%20the%20axis%20is%20undefined%20and%20returned%20as%20NaN.%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20R%20%3D%20np.asarray(R%2C%20dtype%3Dfloat)%0A%20%20%20%20angle%20%3D%20np.degrees(np.arccos(np.clip((np.trace(R)%20-%201)%20%2F%202%2C%20-1%2C%201)))%0A%20%20%20%20w%20%3D%20np.array(%5BR%5B2%2C%201%5D%20-%20R%5B1%2C%202%5D%2C%20R%5B0%2C%202%5D%20-%20R%5B2%2C%200%5D%2C%20R%5B1%2C%200%5D%20-%20R%5B0%2C%201%5D%5D)%0A%20%20%20%20if%20np.linalg.norm(w)%20%3E%201e-9%3A%20%20%23%200%20%3C%20angle%20%3C%20180%0A%20%20%20%20%20%20%20%20return%20w%20%2F%20np.linalg.norm(w)%2C%20angle%0A%20%20%20%20if%20angle%20%3C%2090%3A%20%20%23%20no%20rotation%0A%20%20%20%20%20%20%20%20return%20np.full(3%2C%20np.nan)%2C%20angle%0A%20%20%20%20B%20%3D%20(R%20%2B%20np.eye(3))%20%2F%202%20%20%23%20half%20turn%3A%20B%20%3D%20n%20n%5ET%0A%20%20%20%20n%20%3D%20B%5B%3A%2C%20np.argmax(np.diag(B))%5D%0A%20%20%20%20return%20n%20%2F%20np.linalg.norm(n)%2C%20angle%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20what%20single%20rotation%20is%20equivalent%20to%20%2490%5Eo%24%20about%20%24%5Cmathbf%7BX%7D%24%2C%20then%20%2490%5Eo%24%20about%20%24%5Cmathbf%7BY%7D%24%2C%20then%20%2490%5Eo%24%20about%20%24%5Cmathbf%7BZ%7D%24%20(you%20saw%20its%20matrix%20earlier%2C%20with%20the%20sliders%20at%20their%20initial%20values)%3F%20And%20how%20large%20is%20the%20single%20rotation%20equivalent%20to%20%2430%5Eo%24%2C%20%2445%5Eo%24%20and%20%2460%5Eo%24%20about%20the%20same%20axes%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_cases%20%3D%20%5B%0A%20%20%20%20%20%20%20%20(%2290%20about%20X%2C%20then%2090%20about%20Y%2C%20then%2090%20about%20Z%22%2C%20rotZ(90)%20%40%20rotY(90)%20%40%20rotX(90))%2C%0A%20%20%20%20%20%20%20%20(%22Codman's%20movement%22%2C%20rotX(90)%20%40%20rotY(-90)%20%40%20rotZ(90))%2C%0A%20%20%20%20%20%20%20%20(%2230%20about%20X%2C%20then%2045%20about%20Y%2C%20then%2060%20about%20Z%22%2C%20rotZ(60)%20%40%20rotY(45)%20%40%20rotX(30))%2C%0A%20%20%20%20%5D%0A%20%20%20%20for%20_name%2C%20_R%20in%20_cases%3A%0A%20%20%20%20%20%20%20%20_axis%2C%20_angle%20%3D%20axis_angle(_R)%0A%20%20%20%20%20%20%20%20print(f%22%7B_name%3A46s%7D%20-%3E%20%7B_angle%3A5.1f%7D%20degrees%20about%20%7B_axis.round(3)%20%2B%200.0%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Three%20quarter%20turns%2C%20about%20three%20different%20axes%2C%20add%20up%20to%20a%20single%20quarter%20turn%20about%20%24%5Cmathbf%7BY%7D%24.%20Codman's%20movement%20is%20a%20quarter%20turn%20about%20%24-%5Cmathbf%7BY%7D%24%2C%20which%20is%20the%20rotation%20of%20%24-90%5Eo%24%20about%20%24%5Cmathbf%7BY%7D%24%20found%20before%3A%20the%20function%20always%20reports%20an%20angle%20between%20%240%5Eo%24%20and%20%24180%5Eo%24%2C%20and%20lets%20the%20direction%20of%20the%20axis%20carry%20the%20sign.%20And%20rotations%20of%20%2430%5Eo%24%2C%20%2445%5Eo%24%20and%20%2460%5Eo%24%20add%20up%20to%20a%20single%20rotation%20of%20%2469.4%5Eo%24%2C%20not%20%24135%5Eo%24.%0A%0A%20%20%20%20Unlike%20the%20three%20Euler%20angles%2C%20this%20angle%20does%20not%20depend%20on%20any%20convention%3A%20whatever%20sequence%20you%20choose%20to%20describe%20the%20orientation%2C%20the%20single%20equivalent%20rotation%20is%20the%20same.%20It%20is%20the%20rotational%20part%20of%20the%20helical%20(or%20screw)%20axis%20used%20to%20describe%20joint%20motion%2C%20and%20a%20convenient%2C%20sequence-free%20answer%20to%20the%20question%20%22how%20much%20did%20this%20segment%20rotate%3F%22.%20Problem%2010%20asks%20you%20to%20go%20the%20other%20way%2C%20from%20an%20axis%20and%20an%20angle%20to%20the%20rotation%20matrix.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20How%20much%20does%20the%20order%20matter%3F%0A%0A%20%20%20%20Two%20quarter%20turns%20about%20%24%5Cmathbf%7BZ%7D%24%20and%20%24%5Cmathbf%7BX%7D%24%20ended%20in%20completely%20different%20places%20depending%20on%20their%20order.%20Are%20joint%20angles%20of%20a%20few%20degrees%20just%20as%20sensitive%3F%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20one%20body%20is%20turned%20by%20%2410%5Eo%24%20about%20%24%5Cmathbf%7BZ%7D%24%20and%20then%20by%20%2410%5Eo%24%20about%20%24%5Cmathbf%7BX%7D%24%2C%20and%20another%20body%20by%20the%20same%20two%20rotations%20in%20the%20opposite%20order.%20By%20how%20much%20do%20their%20final%20orientations%20differ%3F%20And%20for%20%2445%5Eo%24%3F%0A%0A%20%20%20%20The%20difference%20between%20two%20orientations%20is%20itself%20a%20rotation%2C%20%24%5Cmathbf%7BR_1%5ET%7D%5Cmathbf%7BR_2%7D%24%2C%20and%20%60axis_angle%60%20measures%20it%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20print(%22%20angle%20%20%20%20Z%20then%20X%20vs%20X%20then%20Z%3A%20differ%20by%20%20%20%20axis%20of%20the%20difference%22)%0A%20%20%20%20for%20_theta%20in%20%5B1%2C%205%2C%2010%2C%2020%2C%2045%2C%2090%5D%3A%0A%20%20%20%20%20%20%20%20_z_then_x%20%3D%20rotX(_theta)%20%40%20rotZ(_theta)%0A%20%20%20%20%20%20%20%20_x_then_z%20%3D%20rotZ(_theta)%20%40%20rotX(_theta)%0A%20%20%20%20%20%20%20%20_axis%2C%20_diff%20%3D%20axis_angle(_z_then_x.T%20%40%20_x_then_z)%0A%20%20%20%20%20%20%20%20print(f%22%7B_theta%3A5d%7D%20%20%20%20%7B_diff%3A10.3f%7D%20degrees%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B_axis.round(2)%20%2B%200.0%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20For%20rotations%20of%20%241%5Eo%24%2C%20the%20two%20orders%20end%20within%20%240.02%5Eo%24%20of%20each%20other%3B%20for%20%2410%5Eo%24%2C%20within%20%241.7%5Eo%24%3B%20for%20%2420%5Eo%24%2C%20%246.9%5Eo%24%3B%20for%20%2445%5Eo%24%2C%20%2434%5Eo%24%3B%20and%20the%20two%20quarter%20turns%20end%20%24120%5Eo%24%20apart.%20The%20difference%20grows%20roughly%20with%20the%20square%20of%20the%20angle%3A%20ten%20times%20the%20angle%2C%20a%20hundred%20times%20the%20difference.%20For%20small%20angles%20it%20is%20a%20rotation%20about%20%24%5Cmathbf%7BY%7D%24%2C%20the%20axis%20perpendicular%20to%20the%20two%20that%20were%20used%3B%20Problem%2011%20asks%20you%20to%20show%20why.%0A%0A%20%20%20%20Small%20rotations%20nearly%20commute.%20That%20is%20why%2C%20for%20a%20joint%20that%20moves%20little%20outside%20its%20main%20plane%2C%20different%20sequences%20of%20Euler%20angles%20give%20nearly%20the%20same%20angles%2C%20and%20why%20the%20choice%20of%20sequence%20matters%20most%20for%20large%20three-dimensional%20movements%2C%20such%20as%20those%20of%20the%20shoulder%20or%20of%20the%20hip%20in%20sport.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20The%2012%20different%20sequences%20of%20Euler%20angles%0A%0A%20%20%20%20The%20Euler%20angles%20are%20defined%20in%20terms%20of%20rotations%20about%20a%20rotating%20local%20coordinate%20system.%20As%20we%20saw%20for%20the%20sequence%20of%20rotations%20about%20%24x%2C%20y%2C%20z%24%2C%20the%20axes%20of%20the%20local%20coordinate%20system%20are%20not%20fixed%20in%20space%3A%20after%20the%20first%20elemental%20rotation%2C%20the%20other%20two%20axes%20have%20moved.%0A%0A%20%20%20%20Other%20sequences%20of%20rotations%20can%20be%20formed%20without%20mixing%20axes%20of%20the%20two%20coordinate%20systems%20(Global%20and%20local)%20as%20rotation%20axes.%20There%20are%2012%20valid%20sequences%20of%20three%20elemental%20rotations%20that%20can%20describe%20the%20rotation%20of%20a%20coordinate%20system%20with%20respect%20to%20another%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20xyz%20%5Cquad%20xzy%20%5Cquad%20yzx%20%5Cquad%20yxz%20%5Cquad%20zxy%20%5Cquad%20zyx%20%20%5C%5C%0A%20%20%20%20xyx%20%5Cquad%20xzx%20%5Cquad%20yzy%20%5Cquad%20yxy%20%5Cquad%20zxz%20%5Cquad%20zyz%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20first%20six%20sequences%20(first%20row)%20are%20about%20three%20different%20axes%20and%20are%20usually%20referred%20to%20as%20Cardan%20or%20Tait%E2%80%93Bryan%20angles.%20The%20other%20six%20(second%20row)%20have%20the%20first%20and%20third%20rotations%20about%20the%20same%20axis%2C%20but%20keep%20in%20mind%20that%20the%20axis%20of%20the%20third%20rotation%20is%20no%20longer%20where%20it%20was%2C%20because%20it%20changed%20orientation%20with%20the%20second%20rotation.%20The%20sequences%20with%20a%20repeated%20axis%20are%20known%20as%20proper%20or%20classic%20Euler%20angles.%0A%0A%20%20%20%20Which%20order%20to%20use%20is%20a%20matter%20of%20convention%2C%20but%20because%20the%20order%20affects%20the%20results%2C%20it%20is%20fundamental%20to%20follow%20a%20convention%20and%20to%20report%20it.%20In%20engineering%20mechanics%20(including%20biomechanics)%2C%20the%20%24xyz%24%20order%20is%20more%20common%3B%20in%20physics%2C%20the%20%24zxz%24%20order%20is%20more%20common%20(but%20the%20letters%20chosen%20for%20the%20axes%20are%20arbitrary%3B%20what%20matters%20is%20the%20directions%20they%20represent).%20In%20biomechanics%2C%20the%20order%20of%20the%20Cardan%20angles%20is%20most%20often%20based%20on%20the%20angle%20of%20most%20interest%20or%20of%20most%20reliable%20measurement.%20Accordingly%2C%20the%20axis%20of%20flexion%E2%80%93extension%20is%20typically%20the%20first%20axis%2C%20the%20axis%20of%20abduction%E2%80%93adduction%20the%20second%2C%20and%20the%20axis%20of%20internal%E2%80%93external%20rotation%20the%20last%20one%3B%20for%20the%20knee%2C%20this%20is%20the%20order%20of%20the%20joint%20coordinate%20system%20of%20Grood%20and%20Suntay%20(1983).%20The%20%24zyx%24%20order%20is%20commonly%20used%20to%20describe%20the%20orientation%20of%20a%20ship%20or%20an%20aircraft%2C%20and%20the%20rotations%20are%20known%20as%20the%20nautical%20angles%3A%20yaw%2C%20pitch%20and%20roll%2C%20respectively%20(see%20next%20figure).%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-9%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F1%2F16%2FYaw_Axis.svg%2F330px-Yaw_Axis.svg.png%22%20width%3D320%20alt%3D%22principal%20axes%20of%20an%20aircraft%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-9%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20The%20principal%20axes%20of%20an%20aircraft%20and%20the%20names%20of%20the%20rotations%20about%20them%20(%3Ca%20href%3D%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FEuler_angles%22%3Eimage%20from%20Wikipedia%3C%2Fa%3E).%3C%2Fspan%3E%0A%0A%20%20%20%20If%2C%20instead%20of%20rotations%20about%20the%20rotating%20local%20coordinate%20system%2C%20we%20perform%20rotations%20about%20the%20fixed%20Global%20coordinate%20system%2C%20we%20have%20another%2012%20sequences%20of%20three%20elemental%20rotations%2C%20called%20simply%20rotation%20angles.%20In%20total%20there%20are%2024%20possible%20sequences%2C%20but%20they%20are%20not%20independent%3A%20with%20the%2012%20sequences%20of%20Euler%20angles%20in%20the%20local%20coordinate%20system%20we%20can%20obtain%20the%20other%2012%20in%20the%20Global%20coordinate%20system.%0A%0A%20%20%20%20The%20function%20below%20determines%20the%20rotation%20matrix%20in%20algebraic%20form%20for%20any%20of%20the%2024%20sequences%20(sequences%20of%20only%20one%20or%20two%20axes%20can%20also%20be%20entered)%2C%20and%20in%20numerical%20form%20if%20a%20list%20of%20angles%20is%20given.%20It%20is%20a%20compact%20version%20of%20the%20function%20%60euler_rotmat.py%60%2C%20from%20the%20%60functions%60%20folder%20of%20this%20repository.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20euler_rotmat(order%3D%22xyz%22%2C%20frame%3D%22local%22%2C%20angles%3DNone%2C%20unit%3D%22deg%22)%3A%0A%20%20%20%20%22%22%22Rotation%20matrix%20for%20a%20sequence%20of%20up%20to%20three%20elemental%20rotations.%0A%0A%20%20%20%20%60order%60%20is%20a%20string%20of%20one%20to%20three%20letters%20among%20x%2C%20y%20and%20z%3B%20the%20first%0A%20%20%20%20letter%20is%20the%20first%20rotation.%20With%20frame%3D%22local%22%2C%20the%20rotations%20are%20about%0A%20%20%20%20the%20axes%20of%20the%20rotating%20coordinate%20system%20(Euler%20angles)%20and%20the%20matrix%20is%0A%20%20%20%20Global-to-local%3B%20with%20frame%3D%22global%22%2C%20they%20are%20about%20the%20fixed%20axes%20and%20the%0A%20%20%20%20matrix%20is%20local-to-Global.%20The%20angles%20of%20the%20first%2C%20second%20and%20third%0A%20%20%20%20rotations%20are%20the%20symbols%20alpha%2C%20beta%20and%20gamma.%0A%0A%20%20%20%20Returns%20the%20algebraic%20matrix%20and%2C%20if%20%60angles%60%20is%20given%2C%20also%20the%20matrix%20with%0A%20%20%20%20those%20values%20substituted%20(use%20None%20for%20an%20angle%20that%20stays%20symbolic).%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20sympy%20as%20sym%0A%0A%20%20%20%20cos%2C%20sin%20%3D%20sym.cos%2C%20sym.sin%0A%20%20%20%20symbols%20%3D%20sym.symbols(%22alpha%2C%20beta%2C%20gamma%22)%0A%0A%20%20%20%20def%20elemental(axis%2C%20q)%3A%0A%20%20%20%20%20%20%20%20R%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%3A%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20cos(q)%2C%20sin(q)%5D%2C%20%5B0%2C%20-sin(q)%2C%20cos(q)%5D%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22y%22%3A%20sym.Matrix(%5B%5Bcos(q)%2C%200%2C%20-sin(q)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5Bsin(q)%2C%200%2C%20cos(q)%5D%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22z%22%3A%20sym.Matrix(%5B%5Bcos(q)%2C%20sin(q)%2C%200%5D%2C%20%5B-sin(q)%2C%20cos(q)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%2C%0A%20%20%20%20%20%20%20%20%7D%5Baxis%5D%0A%20%20%20%20%20%20%20%20return%20R.T%20if%20frame.lower()%20%3D%3D%20%22global%22%20else%20R%0A%0A%20%20%20%20R%20%3D%20sym.eye(3)%0A%20%20%20%20for%20axis%2C%20q%20in%20zip(order.lower()%2C%20symbols)%3A%0A%20%20%20%20%20%20%20%20R%20%3D%20elemental(axis%2C%20q)%20*%20R%20%20%23%20the%20matrix%20product%20goes%20from%20right%20to%20left%0A%20%20%20%20if%20angles%20is%20None%3A%0A%20%20%20%20%20%20%20%20return%20R%0A%0A%20%20%20%20values%20%3D%20%7B%7D%0A%20%20%20%20for%20q%2C%20angle%20in%20zip(symbols%2C%20angles)%3A%0A%20%20%20%20%20%20%20%20if%20angle%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20values%5Bq%5D%20%3D%20sym.rad(angle)%20if%20unit%5B%3A3%5D.lower()%20%3D%3D%20%22deg%22%20else%20angle%0A%20%20%20%20return%20R%2C%20sym.simplify(R.subs(values))%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20For%20instance%2C%20here%20are%20the%20rotation%20matrix%20in%20algebraic%20form%20for%20the%20%24zxz%24%20order%20of%20Euler%20angles%20in%20the%20local%20coordinate%20system%2C%20and%20the%20corresponding%20numerical%20matrix%20after%20three%20elemental%20rotations%20by%20%2490%5Eo%24%20each%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20_Ra%2C%20_Rn%20%3D%20euler_rotmat(order%3D%22zxz%22%2C%20frame%3D%22local%22%2C%20angles%3D%5B90%2C%2090%2C%2090%5D)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7Blocal%7D(z%3A%5Calpha%2C%20x%3A%5Cbeta%2C%20z%3A%5Cgamma)%22%2C%20_Ra)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7Blocal%7D(z%3A90%5Eo%2C%20x%3A90%5Eo%2C%20z%3A90%5Eo)%22%2C%20_Rn)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Line%20of%20nodes%0A%0A%20%20%20%20The%20second%20axis%20of%20rotation%20in%20the%20rotating%20coordinate%20system%20is%20also%20referred%20to%20as%20the%20nodal%20axis%2C%20or%20line%20of%20nodes.%20It%20coincides%20with%20the%20intersection%20of%20two%20perpendicular%20planes%2C%20one%20from%20each%20coordinate%20system%2C%20Global%20(fixed)%20and%20local%20(rotating).%20The%20figure%20below%20shows%20an%20example%20of%20rotations%20and%20the%20nodal%20axis%20for%20the%20%24xyz%24%20sequence%20of%20Cardan%20angles.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-10%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2FNode.png%3Fraw%3D1%22%20width%3D700%20alt%3D%22line%20of%20nodes%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-10%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20First%20row%3A%20example%20of%20rotations%20for%20the%20%24xyz%24%20sequence%20of%20Cardan%20angles.%20The%20Global%20(fixed)%20%24XYZ%24%20coordinate%20system%20is%20shown%20in%20green%2C%20the%20local%20(rotating)%20%24xyz%24%20coordinate%20system%20in%20blue.%20The%20nodal%20axis%20(%3Cb%3EN%3C%2Fb%3E%2C%20in%20red)%20is%20defined%20by%20the%20intersection%20of%20the%20%24YZ%24%20and%20%24xy%24%20planes%2C%20and%20all%20rotations%20can%20be%20described%20in%20relation%20to%20this%20nodal%20axis%20or%20to%20an%20axis%20perpendicular%20to%20it.%20Second%20row%3A%20starting%20from%20no%20rotation%2C%20the%20local%20coordinate%20system%20is%20rotated%20by%20%24%5Calpha%24%20about%20the%20%24x%24%20axis%2C%20then%20by%20%24%5Cbeta%24%20about%20the%20rotated%20%24y%24%20axis%2C%20and%20finally%20by%20%24%5Cgamma%24%20about%20the%20twice-rotated%20%24z%24%20axis.%20The%20line%20of%20nodes%20coincides%20with%20the%20%24y%24%20axis%20of%20the%20second%20rotation.%3C%2Fspan%3E%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Determination%20of%20the%20Euler%20angles%0A%0A%20%20%20%20Once%20a%20convention%20is%20adopted%2C%20the%20corresponding%20three%20Euler%20angles%20can%20be%20found%20from%20the%20rotation%20matrix.%20For%20example%2C%20for%20the%20%24%5Cmathbf%7BR%7D_%7Bxyz%7D%24%20rotation%20matrix%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7Blocal%7D(x%3A%5Calpha%2C%20y%3A%5Cbeta%2C%20z%3A%5Cgamma)%22%2C%20euler_rotmat(order%3D%22xyz%22%2C%20frame%3D%22local%22))%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20corresponding%20Cardan%20angles%20for%20the%20%24xyz%24%20sequence%20are%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20%5Calpha%20%3D%20%5Carctan%5Cleft(%5Cdfrac%7B%5Csin(%5Calpha)%7D%7B%5Ccos(%5Calpha)%7D%5Cright)%20%3D%20%5Carctan%5Cleft(%5Cdfrac%7B-%5Cmathbf%7BR%7D_%7B21%7D%7D%7B%5C%3B%5C%3B%5C%3B%5Cmathbf%7BR%7D_%7B22%7D%7D%5Cright)%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%5Cbeta%20%3D%20%5Carctan%5Cleft(%5Cdfrac%7B%5Csin(%5Cbeta)%7D%7B%5Ccos(%5Cbeta)%7D%5Cright)%20%3D%20%5Carctan%5Cleft(%5Cdfrac%7B%5Cmathbf%7BR%7D_%7B20%7D%7D%7B%5Csqrt%7B%5Cmathbf%7BR%7D_%7B00%7D%5E2%2B%5Cmathbf%7BR%7D_%7B10%7D%5E2%7D%7D%5Cright)%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%5Cgamma%20%3D%20%5Carctan%5Cleft(%5Cdfrac%7B%5Csin(%5Cgamma)%7D%7B%5Ccos(%5Cgamma)%7D%5Cright)%20%3D%20%5Carctan%5Cleft(%5Cdfrac%7B-%5Cmathbf%7BR%7D_%7B10%7D%7D%7B%5C%3B%5C%3B%5C%3B%5Cmathbf%7BR%7D_%7B00%7D%7D%5Cright)%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20(with%20the%20rows%20and%20columns%20numbered%20from%200%2C%20as%20in%20Python).%20We%20use%20the%20function%20%60arctan2%60%20rather%20than%20%60arcsin%60%2C%20%60arccos%60%20or%20%60arctan%60%2C%20because%20those%20cannot%2C%20for%20example%2C%20distinguish%20%2445%5Eo%24%20from%20%24135%5Eo%24%2C%20and%20for%20better%20numerical%20accuracy%3B%20see%20%5BAngular%20kinematics%20in%20a%20plane%20(2D)%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_angular_2d.py)%20for%20more%20on%20these%20issues.%0A%0A%20%20%20%20Here%20is%20a%20Python%20function%20that%20computes%20the%20Euler%20angles%20of%20the%20rotation%20from%20the%20Global%20to%20the%20local%20coordinate%20system%20for%20the%20%24xyz%24%20Cardan%20sequence%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20euler_angles_from_rot_xyz(rot_matrix%2C%20unit%3D%22deg%22)%3A%0A%20%20%20%20%22%22%22Compute%20Euler%20angles%20from%20rotation%20matrix%20in%20the%20xyz%20sequence.%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20R%20%3D%20np.asarray(rot_matrix%2C%20dtype%3Dnp.float64)%5B%3A3%2C%20%3A3%5D%0A%20%20%20%20angles%20%3D%20np.zeros(3)%0A%0A%20%20%20%20angles%5B0%5D%20%3D%20np.arctan2(-R%5B2%2C%201%5D%2C%20R%5B2%2C%202%5D)%0A%20%20%20%20angles%5B1%5D%20%3D%20np.arctan2(R%5B2%2C%200%5D%2C%20np.sqrt(R%5B0%2C%200%5D%20**%202%20%2B%20R%5B1%2C%200%5D%20**%202))%0A%20%20%20%20angles%5B2%5D%20%3D%20np.arctan2(-R%5B1%2C%200%5D%2C%20R%5B0%2C%200%5D)%0A%0A%20%20%20%20if%20unit%5B%3A3%5D.lower()%20%3D%3D%20%22deg%22%3A%20%20%23%20convert%20from%20rad%20to%20degree%0A%20%20%20%20%20%20%20%20angles%20%3D%20np.rad2deg(angles)%0A%0A%20%20%20%20return%20angles%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20For%20instance%2C%20consider%20sequential%20rotations%20of%20%2445%5Eo%24%20about%20%24x%24%2C%20%24y%24%2C%20%24z%24.%20The%20resulting%20rotation%20matrix%20is%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_Ra%2C%20Rn45%20%3D%20euler_rotmat(order%3D%22xyz%22%2C%20frame%3D%22local%22%2C%20angles%3D%5B45%2C%2045%2C%2045%5D)%0A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7Blocal%7D(x%3A45%5Eo%2C%20y%3A45%5Eo%2C%20z%3A45%5Eo)%22%2C%20Rn45%2C%20digits%3D4)%0A%20%20%20%20return%20(Rn45%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Let's%20check%20by%20calculating%20the%20Cardan%20angles%20back%20from%20this%20rotation%20matrix%20with%20%60euler_angles_from_rot_xyz()%60%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Rn45)%3A%0A%20%20%20%20euler_angles_from_rot_xyz(Rn45%2C%20unit%3D%22deg%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20We%20could%20implement%20a%20function%20to%20calculate%20the%20Euler%20angles%20for%20each%20of%20the%2012%20sequences%20(24%2C%20counting%20the%20rotations%20from%20and%20to%20both%20coordinate%20systems)%2C%20but%20this%20is%20tedious.%20There%20is%20a%20smarter%20solution%20using%20the%20concept%20of%20%5Bquaternion%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FQuaternion)%2C%20but%20we%20will%20not%20see%20it%20here.%0A%0A%20%20%20%20**Exercise%204.**%20The%20round%20trip%20gave%20back%20the%20angles%20we%20put%20in%2C%20but%20the%20angles%20that%20produce%20a%20given%20rotation%20matrix%20are%20not%20unique.%20The%20matrix%20%24%5Cmathbf%7BR%7D_%7Blocal%7D(x%3A10%5Eo%2C%20y%3A-30%5Eo%2C%20z%3A50%5Eo)%24%20gives%20back%20exactly%20%24(10%5Eo%2C%20-30%5Eo%2C%2050%5Eo)%24.%20Find%20another%20set%20of%20three%20%24xyz%24%20angles%20that%20produces%20the%20same%20matrix%2C%20and%20check%20it%20with%20%60euler_rotmat%60.%20(Hint%3A%20start%20by%20adding%20%24180%5Eo%24%20to%20the%20first%20and%20the%20third%20angles%2C%20and%20see%20what%20the%20second%20one%20must%20do%20to%20compensate.)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo%2C%20np)%3A%0A%20%20%20%20_%2C%20_R%20%3D%20euler_rotmat(order%3D%22xyz%22%2C%20frame%3D%22local%22%2C%20angles%3D%5B10%2C%20-30%2C%2050%5D)%0A%20%20%20%20_%2C%20_R_alt%20%3D%20euler_rotmat(order%3D%22xyz%22%2C%20frame%3D%22local%22%2C%20angles%3D%5B190%2C%20210%2C%20230%5D)%0A%20%20%20%20_same%20%3D%20np.allclose(np.array(_R%2C%20dtype%3Dfloat)%2C%20np.array(_R_alt%2C%20dtype%3Dfloat))%0A%20%20%20%20_back%20%3D%20euler_angles_from_rot_xyz(np.array(_R_alt%2C%20dtype%3Dfloat)).round(4)%20%2B%200.0%0A%0A%20%20%20%20mo.accordion(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Solution%20to%20Exercise%204%22%3A%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rf%22%22%22%0A%20%20%20%20Adding%20%24180%5Eo%24%20to%20%24%5Calpha%24%20changes%20the%20sign%20of%20both%20%24%5Csin%5Calpha%24%20and%20%24%5Ccos%5Calpha%24%2C%20and%20the%20same%20for%20%24%5Cgamma%24.%20To%20compensate%2C%20the%20second%20angle%20must%20keep%20its%20sine%20and%20change%20the%20sign%20of%20its%20cosine%2C%20which%20%24180%5Eo%20-%20%5Cbeta%24%20does.%20Every%20entry%20of%20the%20matrix%20is%20then%20a%20product%20in%20which%20either%20none%20or%20exactly%20two%20of%20the%20factors%20change%20sign%2C%20so%20the%20matrix%20does%20not%20change.%20The%20second%20set%20of%20angles%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20(%5Calpha%20%2B%20180%5Eo%2C%5C%3B%20180%5Eo%20-%20%5Cbeta%2C%5C%3B%20%5Cgamma%20%2B%20180%5Eo)%20%3D%20(190%5Eo%2C%5C%3B%20210%5Eo%2C%5C%3B%20230%5Eo)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20or%2C%20written%20between%20%24-180%5Eo%24%20and%20%24180%5Eo%24%2C%20%24(-170%5Eo%2C%20-150%5Eo%2C%20-130%5Eo)%24.%0A%0A%20%20%20%20Same%20matrix%3A%20%7B_same%7D.%20And%20%60euler_angles_from_rot_xyz%60%20applied%20to%20this%20matrix%20returns%20%7B_back%7D%2C%20the%20first%20solution%20again.%0A%0A%20%20%20%20The%20function%20always%20picks%20the%20solution%20with%20%24%5Ccos%5Cbeta%20%5Cgeq%200%24%2C%20that%20is%2C%20with%20%24%5Cbeta%24%20between%20%24-90%5Eo%24%20and%20%2490%5Eo%24%2C%20because%20it%20computes%20the%20cosine%20of%20%24%5Cbeta%24%20as%20a%20positive%20square%20root.%20That%20choice%20is%20a%20convention%20too%2C%20and%20it%20is%20the%20reason%20why%20the%20second%20angle%20of%20a%20Cardan%20sequence%20is%20reported%20between%20%24-90%5Eo%24%20and%20%2490%5Eo%24.%0A%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Apart%20from%20that%20choice%20between%20two%20solutions%2C%20the%20round%20trip%20worked%20here.%20It%20does%20not%20always%20work%2C%20and%20the%20reason%20is%20a%20problem%20of%20Euler%20angles%20known%20as%20gimbal%20lock.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Gimbal%20lock%0A%0A%20%20%20%20%5BGimbal%20lock%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FGimbal_lock)%20is%20the%20loss%20of%20one%20degree%20of%20freedom%20that%20occurs%20when%20an%20axis%20of%20rotation%20is%20placed%20parallel%20to%20a%20previous%20axis%20of%20rotation%2C%20so%20that%2C%20in%20a%20given%20convention%20of%20Euler%20angles%2C%20two%20of%20the%20three%20rotations%20are%20about%20the%20same%20direction.%20This%20%22locks%22%20the%20system%20into%20rotations%20in%20a%20degenerate%20two-dimensional%20space.%20The%20system%20is%20not%20really%20locked%2C%20in%20the%20sense%20that%20it%20cannot%20move%20or%20cannot%20reach%20the%20other%20degree%20of%20freedom%2C%20but%20it%20needs%20an%20extra%20rotation%20for%20that.%0A%0A%20%20%20%20For%20instance%2C%20look%20at%20the%20%24zxz%24%20sequence%20of%20rotations%20by%20the%20angles%20%24%5Calpha%2C%20%5Cbeta%2C%20%5Cgamma%24%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20%5Cmathbf%7BR%7D_%7Bzxz%7D%20%26%20%3D%20%5Cmathbf%7BR_%7Bz%7D%7D%20%5Cmathbf%7BR_%7Bx%7D%7D%20%5Cmathbf%7BR_%7Bz%7D%7D%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%26%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cgamma%20%26%20%5Csin%5Cgamma%20%26%200%5C%5C%0A%20%20%20%20-%5Csin%5Cgamma%20%26%20%5Ccos%5Cgamma%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%201%20%26%200%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%20%5Ccos%5Cbeta%20%26%20%5Csin%5Cbeta%20%5C%5C%0A%20%20%20%200%20%26%20-%5Csin%5Cbeta%20%26%20%5Ccos%5Cbeta%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20%5Csin%5Calpha%20%26%200%5C%5C%0A%20%20%20%20-%5Csin%5Calpha%20%26%20%5Ccos%5Calpha%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20which%20results%20in%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(a%2C%20b%2C%20cos%2C%20g%2C%20sin%2C%20sym)%3A%0A%20%20%20%20%23%20Elemental%20rotation%20matrices%20of%20xyz%20(local)%20for%20the%20zxz%20sequence%3A%0A%20%20%20%20Rz1%20%3D%20sym.Matrix(%5B%5Bcos(a)%2C%20sin(a)%2C%200%5D%2C%20%5B-sin(a)%2C%20cos(a)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%20%20%20%20Rx2%20%3D%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20cos(b)%2C%20sin(b)%5D%2C%20%5B0%2C%20-sin(b)%2C%20cos(b)%5D%5D)%0A%20%20%20%20Rz3%20%3D%20sym.Matrix(%5B%5Bcos(g)%2C%20sin(g)%2C%200%5D%2C%20%5B-sin(g)%2C%20cos(g)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%0A%20%20%20%20%23%20Rotation%20matrix%20for%20the%20zxz%20sequence%3A%0A%20%20%20%20Rzxz%20%3D%20Rz3%20*%20Rx2%20*%20Rz1%0A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7Bzxz%7D%22%2C%20Rzxz)%0A%20%20%20%20return%20Rz1%2C%20Rz3%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Let's%20examine%20what%20happens%20to%20this%20rotation%20matrix%20when%20the%20rotation%20about%20the%20second%20axis%20(%24x%24)%20by%20%24%5Cbeta%24%20is%20zero%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR%7D_%7Bzxz%7D(%5Calpha%2C%20%5Cbeta%3D0%2C%20%5Cgamma)%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cgamma%20%26%20%5Csin%5Cgamma%20%26%200%5C%5C%0A%20%20%20%20-%5Csin%5Cgamma%20%26%20%5Ccos%5Cgamma%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%201%20%26%200%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%201%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20%5Csin%5Calpha%20%26%200%5C%5C%0A%20%20%20%20-%5Csin%5Calpha%20%26%20%5Ccos%5Calpha%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20second%20matrix%20is%20the%20identity%20matrix%20and%20has%20no%20effect%20on%20the%20product%2C%20which%20is%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Rz1%2C%20Rz3%2C%20mo%2C%20sym)%3A%0A%20%20%20%20_Rzxz0%20%3D%20Rz3%20*%20Rz1%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7Bzxz%7D(%5Calpha%2C%20%5Cbeta%3D0%2C%20%5Cgamma)%22%2C%20_Rzxz0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7Bzxz%7D(%5Calpha%2C%20%5Cbeta%3D0%2C%20%5Cgamma)%22%2C%20sym.simplify(_Rzxz0))%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20which%2C%20after%20simplification%20(above)%2C%20is%20a%20single%20rotation%20about%20the%20%24z%24%20axis%20by%20the%20sum%20%24%5Calpha%2B%5Cgamma%24.%20Whatever%20the%20values%20of%20%24%5Calpha%24%20and%20%24%5Cgamma%24%2C%20only%20their%20sum%20matters%3A%20of%20the%20three%20degrees%20of%20freedom%2C%20one%20was%20lost%20(and%20another%20was%20fixed%20by%20setting%20%24%5Cbeta%3D0%24).%20For%20movement%20analysis%2C%20this%20means%20that%20one%20angle%20is%20undetermined%2C%20because%20all%20we%20can%20recover%20from%20the%20rotation%20matrix%20is%20the%20sum%20of%20the%20two.%20We%20can%20set%20the%20unknown%20angle%20to%20zero%2C%20but%20that%20is%20arbitrary.%0A%0A%20%20%20%20We%20have%20already%20met%20another%20example%20of%20gimbal%20lock%2C%20in%20the%20%24xyz%24%20sequence%20with%20rotations%20by%20%2490%5Eo%24.%20Look%20again%20at%20the%20figure%20of%20those%20rotations%3A%20the%20first%20and%20third%20rotations%20were%20about%20the%20same%20direction%2C%20because%20the%20second%20rotation%20was%20by%20%2490%5Eo%24.%20Let's%20do%20the%20matrix%20multiplication%20with%20only%20the%20second%20angle%20replaced%20by%20%2490%5Eo%24%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_Ra%2C%20_Rn%20%3D%20euler_rotmat(order%3D%22xyz%22%2C%20frame%3D%22local%22%2C%20angles%3D%5BNone%2C%2090.0%2C%20None%5D)%0A%0A%20%20%20%20show_matrix(r%22%5Cmathbf%7BR%7D_%7Blocal%7D(x%3A%5Calpha%2C%20y%3A90%5Eo%2C%20z%3A%5Cgamma)%22%2C%20_Rn)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Once%20again%2C%20one%20degree%20of%20freedom%20was%20lost%3A%20only%20%24%5Calpha%2B%5Cgamma%24%20appears%2C%20and%20we%20cannot%20determine%20the%20three%20angles%20uniquely%20from%20the%20rotation%20matrix%20of%20this%20sequence.%0A%0A%20%20%20%20%23%23%23%20How%20close%20is%20too%20close%3F%0A%0A%20%20%20%20A%20rotation%20of%20exactly%20%2490%5Eo%24%20is%20rare%20in%20measured%20data.%20Is%20there%20anything%20to%20worry%20about%20at%2C%20say%2C%20%2489%5Eo%24%3F%0A%0A%20%20%20%20Let's%20take%20a%20rotation%20in%20the%20%24xyz%24%20sequence%20with%20%24%5Calpha%20%3D%2030%5Eo%24%2C%20%24%5Cgamma%20%3D%2020%5Eo%24%20and%20different%20values%20of%20%24%5Cbeta%24%2C%20spoil%20each%20matrix%20with%20a%20tiny%20error%2C%20a%20rotation%20of%20about%200.14%C2%B0%20made%20of%200.1%C2%B0%20about%20%24%5Cmathbf%7BX%7D%24%20and%200.1%C2%B0%20about%20%24%5Cmathbf%7BY%7D%24%2C%20much%20smaller%20than%20the%20errors%20of%20a%20real%20measurement%2C%20and%20calculate%20the%20angles%20back.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20how%20large%20will%20the%20errors%20in%20the%20three%20angles%20be%20when%20%24%5Cbeta%20%3D%2045%5Eo%24%3F%20And%20when%20%24%5Cbeta%20%3D%2089.9%5Eo%24%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Rxyz%2C%20a%2C%20b%2C%20g%2C%20np%2C%20sym)%3A%0A%20%20%20%20_R_of%20%3D%20sym.lambdify((a%2C%20b%2C%20g)%2C%20Rxyz%2C%20%22numpy%22)%0A%20%20%20%20_error%20%3D%20rotX(0.1)%20%40%20rotY(0.1)%20%20%23%20a%20small%20error%20in%20the%20orientation%0A%0A%20%20%20%20print(%22%20beta%20%20%20%20%20angles%20from%20the%20slightly%20wrong%20matrix%20%20%20%20errors%20%20%20%20%20%20%20%20%20%20%20alpha%20%2B%20gamma%22)%0A%20%20%20%20for%20_beta%20in%20%5B0%2C%2045%2C%2080%2C%2089%2C%2089.9%2C%2089.99%5D%3A%0A%20%20%20%20%20%20%20%20_true%20%3D%20np.array(%5B30%2C%20_beta%2C%2020%5D)%0A%20%20%20%20%20%20%20%20_back%20%3D%20euler_angles_from_rot_xyz(_R_of(*np.radians(_true))%20%40%20_error)%0A%20%20%20%20%20%20%20%20print(f%22%7B_beta%3A6.2f%7D%20%20%20%7B_back.round(2)%7D%20%20%20%7B(_back%20-%20_true).round(2)%7D%20%20%20%7B_back%5B0%5D%20%2B%20_back%5B2%5D%3A6.2f%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Far%20from%20the%20lock%2C%20an%20error%20of%200.14%C2%B0%20in%20the%20orientation%20becomes%20errors%20of%20about%200.1%C2%B0%20in%20the%20angles%2C%20as%20it%20should.%20As%20%24%5Cbeta%24%20approaches%20%2490%5Eo%24%2C%20the%20errors%20in%20%24%5Calpha%24%20and%20%24%5Cgamma%24%20grow%20without%20bound%3A%20about%202.7%C2%B0%20at%20%24%5Cbeta%20%3D%2089%5Eo%24%2C%2015%C2%B0%20at%20%2489.9%5Eo%24%2C%2027%C2%B0%20at%20%2489.99%5Eo%24.%20Their%20sum%20stays%20close%20to%20%2450%5Eo%24%20throughout.%20Near%20the%20lock%2C%20the%20matrix%20determines%20only%20the%20sum%2C%20and%20the%20split%20between%20the%20two%20angles%20is%20decided%20by%20the%20error.%20So%20gimbal%20lock%20is%20not%20a%20single%20bad%20orientation%20to%20avoid%2C%20but%20a%20region%20around%20it%20where%20two%20of%20the%20angles%20become%20meaningless.%0A%0A%20%20%20%20Possible%20solutions%20to%20avoid%20gimbal%20lock%20are%3A%20choose%20a%20different%20sequence%3B%20avoid%20the%20orientations%20that%20put%20the%20system%20in%20gimbal%20lock%20(in%20the%20examples%20above%2C%20%24%5Cbeta%3D90%5Eo%24)%3B%20or%20add%20a%20fourth%20parameter%20to%20the%20description%20of%20the%20orientation%2C%20as%20quaternions%20do.%0A%0A%20%20%20%20But%20if%20we%20have%20a%20physical%20system%20that%20we%20describe%20or%20control%20with%20exactly%20three%20Euler%20angles%20in%20a%20fixed%20sequence%2C%20and%20we%20cannot%20prevent%20it%20from%20reaching%20certain%20angles%2C%20then%20we%20might%20have%20to%20say%20%22Houston%2C%20we%20have%20a%20problem%22.%20A%20famous%20situation%20where%20this%20happened%20was%20the%20Apollo%2013%20mission.%20This%20is%20an%20actual%20conversation%20between%20the%20crew%20and%20mission%20control%20during%20that%20mission%20(Corke%2C%202011)%3A%0A%0A%20%20%20%20%3E%60Mission%20clock%3A%2002%2008%2012%2047%60%3Cbr%3E%0A%20%20%20%20**Flight**%3A%20*Go%2C%20Guidance.*%3Cbr%3E%0A%20%20%20%20**Guido**%3A%20*He%E2%80%99s%20getting%20close%20to%20gimbal%20lock%20there.*%3Cbr%3E%0A%20%20%20%20**Flight**%3A%20*Roger.%20CapCom%2C%20recommend%20he%20bring%20up%20C3%2C%20C4%2C%20B3%2C%20B4%2C%20C1%20and%20C2%20thrusters%2C%20and%20advise%20he%E2%80%99s%20getting%20close%20to%20gimbal%20lock.*%3Cbr%3E%0A%20%20%20%20**CapCom**%3A%20*Roger.*%0A%0A%20%20%20%20*Of%20note%2C%20gimbal%20lock%20did%20not%20cause%20the%20Apollo%2013%20accident%3B%20the%20problem%20was%20an%20oxygen%20tank%20explosion.*%0A%0A%20%20%20%20**Guiding%20questions%203.**%0A%0A%20%20%20%201.%20For%20which%20value%20of%20%24%5Cbeta%24%20does%20the%20%24zxz%24%20sequence%20lock%3F%20And%20the%20%24xyz%24%20sequence%3F%20Why%20are%20they%20different%3F%0A%20%20%20%202.%20In%20the%20table%20above%2C%20%24%5Cbeta%24%20itself%20is%20recovered%20with%20an%20error%20of%20about%200.1%C2%B0%20all%20the%20way%20to%20the%20lock.%20Why%20is%20the%20second%20angle%20unaffected%3F%0A%20%20%20%203.%20You%20measure%20the%20shoulder%20of%20a%20person%20raising%20the%20arm%20sideways%20to%20above%20the%20head.%20Why%20might%20the%20sequence%20you%20chose%20for%20the%20knee%20be%20a%20poor%20choice%20here%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Determination%20of%20the%20rotation%20matrix%0A%0A%20%20%20%20Let's%20revisit%20the%20example%20where%20we%20determined%20the%20rotation%20matrix%20by%20building%20a%20basis%20from%20three%20noncollinear%20points%2C%20%24%5Cmathbf%7Bm_1%7D%20%3D%20%5B1%2C0%2C0%5D%24%2C%20%24%5Cmathbf%7Bm_2%7D%20%3D%20%5B0%2C1%2C0%5D%24%2C%20%24%5Cmathbf%7Bm_3%7D%20%3D%20%5B0%2C0%2C1%5D%24%2C%20and%20now%20find%20its%20Euler%20angles.%20The%20versors%20of%20the%20basis%2C%20as%20rows%2C%20form%20the%20rotation%20matrix%20from%20the%20Global%20to%20the%20local%20coordinate%20system%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20v1%2C%20v2%2C%20v3)%3A%0A%20%20%20%20_RlG%20%3D%20np.array(%5Bv1%2C%20v2%2C%20v3%5D)%0A%0A%20%20%20%20print(%22Rotation%20matrix%20from%20Global%20to%20local%20coordinate%20system%3A%5Cn%22%2C%20_RlG)%0A%20%20%20%20print(%22%5CnAngles%20of%20rotation%20for%20the%20xyz%20sequence%3A%22%2C%20euler_angles_from_rot_xyz(_RlG))%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20These%20angles%20do%20not%20mean%20anything%20here%2C%20because%20they%20are%20the%20angles%20of%20the%20axes%20of%20the%20arbitrary%20basis%20we%20computed.%20In%20biomechanics%2C%20to%20give%20the%20orientation%20of%20a%20coordinate%20system%20an%20anatomical%20interpretation%2C%20we%20define%20the%20versors%20of%20the%20basis%20along%20anatomical%20axes%20(for%20the%20upper%20arm%2C%20for%20example%2C%20one%20versor%20along%20the%20long%20axis%20of%20the%20humerus)%2C%20as%20seen%20in%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Determination%20of%20the%20rotation%20matrix%20between%20two%20local%20coordinate%20systems%0A%0A%20%20%20%20As%20in%20the%20%5Btwo-dimensional%20case%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_2d.py)%2C%20the%20rotation%20matrix%20between%20two%20local%20coordinate%20systems%20can%20be%20computed%20from%20the%20rotation%20matrices%20of%20both%20coordinate%20systems%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20R_%7Bl_1l_2%7D%20%3D%20R_%7BGl_1%7D%5ETR_%7BGl_2%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20Euler%20angles%20between%20the%20two%20coordinate%20systems%20can%20then%20be%20found%20with%20the%20%60arctan2%60%20function%2C%20as%20shown%20previously.%20This%20is%20how%20a%20joint%20angle%20is%20calculated%3A%20the%20knee%20angle%20is%20the%20orientation%20of%20the%20shank's%20coordinate%20system%20relative%20to%20the%20thigh's.%0A%0A%20%20%20%20For%20example%2C%20suppose%20the%20thigh%20is%20rotated%20from%20the%20laboratory%20by%2030%C2%B0%20about%20%24%5Cmathbf%7BZ%7D%24%20and%20the%20shank%20by%20%24-20%5Eo%24%20about%20%24%5Cmathbf%7BZ%7D%24.%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20the%20rotation%20of%20the%20shank%20relative%20to%20the%20thigh.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_RGl_thigh%20%3D%20rotZ(30)%0A%20%20%20%20_RGl_shank%20%3D%20rotZ(-20)%0A%20%20%20%20_Rl1l2%20%3D%20_RGl_thigh.T%20%40%20_RGl_shank%0A%0A%20%20%20%20print(%22Rotation%20matrix%20of%20the%20shank%20relative%20to%20the%20thigh%3A%5Cn%22%2C%20_Rl1l2.round(4)%20%2B%200.0)%0A%20%20%20%20print(%22Equal%20to%20a%20rotation%20of%20-50%20degrees%20about%20Z%3F%22%2C%20np.allclose(_Rl1l2%2C%20rotZ(-50)))%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20A%20rotation%20of%20%24-50%5Eo%24%20about%20%24%5Cmathbf%7BZ%7D%24%3A%20the%20difference%20between%20the%20two%20angles.%20That%20is%20only%20because%20both%20rotations%20are%20about%20the%20same%20axis%2C%20which%20makes%20this%20a%20two-dimensional%20problem%20in%20disguise.%20As%20soon%20as%20the%20two%20segments%20are%20rotated%20about%20different%20axes%2C%20the%20relative%20angles%20are%20no%20longer%20differences%20of%20angles%3B%20Problem%208%20asks%20you%20to%20show%20it.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Translation%20and%20rotation%0A%0A%20%20%20%20Consider%20the%20case%20where%20the%20local%20coordinate%20system%20is%20translated%20and%20rotated%20in%20relation%20to%20the%20Global%20coordinate%20system%2C%20as%20illustrated%20in%20the%20next%20figure.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-11%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Ftransrot3D.png%3Fraw%3D1%22%20width%3D450%20alt%3D%22translation%20and%20rotation%203D%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-11%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20A%20point%20in%20three-dimensional%20space%20represented%20in%20two%20coordinate%20systems%2C%20with%20one%20coordinate%20system%20translated%20and%20rotated.%3C%2Fspan%3E%0A%0A%20%20%20%20The%20position%20of%20the%20point%20%24%5Cmathbf%7BP%7D%24%2C%20originally%20described%20in%20the%20local%20coordinate%20system%2C%20is%20described%20in%20the%20Global%20coordinate%20system%20in%20vector%20form%20by%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20This%20means%20that%20we%20first%20*disrotate*%20the%20local%20coordinate%20system%20and%20then%20correct%20for%20the%20translation%20between%20the%20two%20coordinate%20systems.%20We%20cannot%20invert%20this%20order%3A%20the%20position%20of%20the%20point%20is%20expressed%20in%20the%20local%20coordinate%20system%2C%20and%20we%20cannot%20add%20it%20to%20a%20vector%20expressed%20in%20the%20Global%20coordinate%20system%20before%20converting%20both%20vectors%20to%20the%20same%20coordinate%20system.%0A%0A%20%20%20%20To%20find%20the%20position%20of%20a%20point%20in%20the%20local%20coordinate%20system%2C%20given%20its%20position%20in%20the%20Global%20coordinate%20system%2C%20the%20rotation%20matrix%20and%20the%20translation%20vector%2C%20we%20invert%20the%20expression%20above%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bll%7D%0A%20%20%20%20%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%20%5Cimplies%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Ccdot%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Cleft(%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%5Cright)%20%5Cimplies%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%20%5Cimplies%20%5C%5C%0A%20%20%20%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Cleft(%5Cmathbf%7BP_G%7D-%5Cmathbf%7BL_G%7D%5Cright)%20%3D%20%20%5Cmathbf%7BR_%7BGl%7D%5ET%7D%5Cleft(%5Cmathbf%7BP_G%7D-%5Cmathbf%7BL_G%7D%5Cright)%20%5C%3B%5C%3B%5C%3B%5C%3B%5C%3B%20%5Ctext%7Bor%7D%20%5C%3B%5C%3B%5C%3B%5C%3B%5C%3B%20%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BR_%7BlG%7D%7D%5Cleft(%5Cmathbf%7BP_G%7D-%5Cmathbf%7BL_G%7D%5Cright)%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20To%20perform%20the%20inverse%20operation%2C%20from%20the%20Global%20to%20the%20local%20coordinate%20system%2C%20we%20first%20translate%20and%20then%20rotate.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Transformation%20matrix%0A%0A%20%20%20%20The%20translation%20and%20rotation%20operations%20can%20be%20combined%20in%20a%20single%20matrix%2C%20called%20the%20transformation%20matrix%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Cmathbf%7BP_X%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Y%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Z%7D%20%5C%5C%0A%20%20%20%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20.%20%26%20.%20%26%20.%20%26%20%5Cmathbf%7BL_%7BX%7D%7D%20%5C%5C%0A%20%20%20%20.%20%26%20%5Cmathbf%7BR_%7BGl%7D%7D%20%26%20.%20%20%26%20%5Cmathbf%7BL_%7BY%7D%7D%20%5C%5C%0A%20%20%20%20.%20%26%20.%20%26%20.%20%20%26%20%5Cmathbf%7BL_%7BZ%7D%7D%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Cmathbf%7BP%7D_x%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP%7D_y%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP%7D_z%20%5C%5C%0A%20%20%20%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20or%20simply%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BT_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Remember%20that%2C%20in%20general%2C%20the%20transformation%20matrix%20is%20not%20orthonormal%3A%20its%20inverse%20is%20not%20equal%20to%20its%20transpose.%0A%0A%20%20%20%20The%20inverse%20operation%2C%20expressing%20a%20position%20given%20in%20the%20Global%20coordinate%20system%20in%20the%20local%20coordinate%20system%2C%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BT_%7BGl%7D%5E%7B-1%7D%7D%5Cmathbf%7BP_G%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Cmathbf%7BP_x%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_y%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_z%7D%20%5C%5C%0A%20%20%20%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccdot%20%26%20%5Ccdot%20%26%20%5Ccdot%20%26%20%5Ccdot%20%5C%5C%0A%20%20%20%20%5Ccdot%20%26%20%5Cmathbf%7BR%5E%7B-1%7D_%7BGl%7D%7D%20%26%20%5Ccdot%20%20%26%20-%5Cmathbf%7BR%5E%7B-1%7D_%7BGl%7D%7D%5C%3A%5Cmathbf%7BL_G%7D%20%5C%5C%0A%20%20%20%20%5Ccdot%20%26%20%5Ccdot%20%26%20%5Ccdot%20%20%26%20%5Ccdot%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Cmathbf%7BP_X%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Y%7D%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Z%7D%20%5C%5C%0A%20%20%20%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Example%20with%20actual%20motion%20analysis%20data%0A%0A%20%20%20%20*The%20data%20for%20this%20example%20are%20taken%20from%20page%20183%20of%20David%20Winter's%20book.*%0A%0A%20%20%20%20Consider%20the%20following%20positions%20of%20markers%20placed%20on%20a%20leg%20(described%20in%20the%20laboratory%20coordinate%20system%20with%20coordinates%20%24x%2C%20y%2C%20z%24%20in%20cm%2C%20the%20%24x%24%20axis%20pointing%20forward%20and%20the%20%24y%24%20axis%20pointing%20upward)%3A%20lateral%20malleolus%20(**lm**%20%3D%20%5B2.92%2C%2010.10%2C%2018.85%5D)%2C%20medial%20malleolus%20(**mm**%20%3D%20%5B2.71%2C%2010.22%2C%2026.52%5D)%2C%20fibular%20head%20(**fh**%20%3D%20%5B5.05%2C%2041.90%2C%2015.41%5D)%20and%20medial%20condyle%20(**mc**%20%3D%20%5B8.29%2C%2041.88%2C%2026.52%5D).%20Define%20the%20ankle%20joint%20center%20as%20the%20centroid%20of%20the%20**lm**%20and%20**mm**%20markers%2C%20and%20the%20knee%20joint%20center%20as%20the%20centroid%20of%20the%20**fh**%20and%20**mc**%20markers.%20An%20anatomical%20coordinate%20system%20for%20the%20leg%20can%20be%20defined%20as%20follows%3A%20the%20quasi-vertical%20axis%20(%24y%24)%20passes%20through%20the%20ankle%20and%20knee%20joint%20centers%3B%20a%20temporary%20medio-lateral%20axis%20(%24z%24)%20passes%20through%20the%20two%20markers%20on%20the%20malleoli%3B%20the%20anterior-posterior%20axis%20is%20the%20cross%20product%20of%20the%20two%20former%20axes%3B%20and%20the%20origin%20is%20at%20the%20ankle%20joint%20center.%0A%0A%20%20%20%20a)%20Calculate%20the%20anatomical%20coordinate%20system%20for%20the%20leg%20as%20described%20above.%3Cbr%3E%0A%20%20%20%20b)%20Calculate%20the%20rotation%20matrix%20and%20the%20translation%20vector%20for%20the%20transformation%20from%20the%20anatomical%20to%20the%20laboratory%20coordinate%20system.%3Cbr%3E%0A%20%20%20%20c)%20Calculate%20the%20position%20of%20each%20marker%20and%20of%20each%20joint%20center%20in%20the%20anatomical%20coordinate%20system.%3Cbr%3E%0A%20%20%20%20d)%20Calculate%20the%20Cardan%20angles%20using%20the%20%24zxy%24%20sequence%20for%20the%20orientation%20of%20the%20leg%20with%20respect%20to%20the%20laboratory%20(but%20remember%20that%20the%20letters%20chosen%20to%20refer%20to%20axes%20are%20arbitrary%3B%20what%20matters%20is%20the%20directions%20they%20represent).%0A%0A%20%20%20%20We%20solve%20parts%20a)%20to%20c)%20here.%20Part%20d)%20is%20Problem%203.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20%23%20calculation%20of%20the%20joint%20centers%0A%20%20%20%20mm%20%3D%20np.array(%5B2.71%2C%2010.22%2C%2026.52%5D)%0A%20%20%20%20lm%20%3D%20np.array(%5B2.92%2C%2010.10%2C%2018.85%5D)%0A%20%20%20%20fh%20%3D%20np.array(%5B5.05%2C%2041.90%2C%2015.41%5D)%0A%20%20%20%20mc%20%3D%20np.array(%5B8.29%2C%2041.88%2C%2026.52%5D)%0A%20%20%20%20ajc%20%3D%20(mm%20%2B%20lm)%20%2F%202%0A%20%20%20%20kjc%20%3D%20(fh%20%2B%20mc)%20%2F%202%0A%0A%20%20%20%20print(%22Position%20of%20the%20ankle%20joint%20center%3A%22%2C%20ajc)%0A%20%20%20%20print(%22Position%20of%20the%20knee%20joint%20center%3A%22%2C%20kjc)%0A%20%20%20%20return%20ajc%2C%20fh%2C%20kjc%2C%20lm%2C%20mc%2C%20mm%0A%0A%0A%40app.cell%0Adef%20_(ajc%2C%20kjc%2C%20lm%2C%20mm%2C%20np)%3A%0A%20%20%20%20%23%20calculation%20of%20the%20anatomical%20coordinate%20system%20axes%20(basis)%0A%20%20%20%20y%20%3D%20kjc%20-%20ajc%0A%20%20%20%20x%20%3D%20np.cross(y%2C%20mm%20-%20lm)%0A%20%20%20%20z%20%3D%20np.cross(x%2C%20y)%0A%20%20%20%20print(%22Versors%3A%22)%0A%20%20%20%20x%20%3D%20x%20%2F%20np.linalg.norm(x)%0A%20%20%20%20y%20%3D%20y%20%2F%20np.linalg.norm(y)%0A%20%20%20%20z%20%3D%20z%20%2F%20np.linalg.norm(z)%0A%20%20%20%20print(%22x%20%3D%22%2C%20x)%0A%20%20%20%20print(%22y%20%3D%22%2C%20y)%0A%20%20%20%20print(%22z%20%3D%22%2C%20z)%0A%20%20%20%20Oleg%20%3D%20ajc%0A%20%20%20%20print(%22%5CnOrigin%20%3D%22%2C%20Oleg)%0A%20%20%20%20return%20Oleg%2C%20x%2C%20y%2C%20z%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20x%2C%20y%2C%20z)%3A%0A%20%20%20%20%23%20Rotation%20matrices%0A%20%20%20%20RGl%20%3D%20np.array(%5Bx%2C%20y%2C%20z%5D).T%0A%20%20%20%20print(%22Rotation%20matrix%20from%20the%20anatomical%20to%20the%20laboratory%20coordinate%20system%3A%5Cn%22%2C%20RGl)%0A%20%20%20%20RlG%20%3D%20RGl.T%0A%20%20%20%20print(%22%5CnRotation%20matrix%20from%20the%20laboratory%20to%20the%20anatomical%20coordinate%20system%3A%5Cn%22%2C%20RlG)%0A%20%20%20%20return%20RGl%2C%20RlG%0A%0A%0A%40app.cell%0Adef%20_(Oleg%2C%20np)%3A%0A%20%20%20%20%23%20Translational%20vector%0A%20%20%20%20OG%20%3D%20np.array(%5B0%2C%200%2C%200%5D)%20%20%23%20Laboratory%20coordinate%20system%20origin%0A%20%20%20%20LG%20%3D%20Oleg%20-%20OG%0A%20%20%20%20print(%22Translational%20vector%20from%20the%20anatomical%20to%20the%20laboratory%20coordinate%20system%3A%5Cn%22%2C%20LG)%0A%20%20%20%20return%20(LG%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20To%20get%20the%20coordinates%20from%20the%20laboratory%20(Global)%20coordinate%20system%20to%20the%20anatomical%20(local)%20coordinate%20system%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BR_%7BlG%7D%7D%5Cleft(%5Cmathbf%7BP_G%7D-%5Cmathbf%7BL_G%7D%5Cright)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20two%20of%20the%20results%20without%20computing%20anything%3A%20the%20coordinates%20of%20the%20ankle%20joint%20center%2C%20and%20two%20of%20the%20three%20coordinates%20of%20the%20knee%20joint%20center.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(LG%2C%20RlG%2C%20ajc%2C%20fh%2C%20kjc%2C%20lm%2C%20mc%2C%20mm%2C%20np)%3A%0A%20%20%20%20%23%20position%20of%20each%20marker%20and%20of%20each%20joint%20center%20in%20the%20anatomical%20coordinate%20system%0A%20%20%20%20mml%20%3D%20np.dot(RlG%2C%20(mm%20-%20LG))%20%20%23%20equivalent%20to%20the%20algebraic%20expression%20RlG*(mm%20-%20LG).T%0A%20%20%20%20lml%20%3D%20np.dot(RlG%2C%20(lm%20-%20LG))%0A%20%20%20%20fhl%20%3D%20np.dot(RlG%2C%20(fh%20-%20LG))%0A%20%20%20%20mcl%20%3D%20np.dot(RlG%2C%20(mc%20-%20LG))%0A%20%20%20%20ajcl%20%3D%20np.dot(RlG%2C%20(ajc%20-%20LG))%0A%20%20%20%20kjcl%20%3D%20np.dot(RlG%2C%20(kjc%20-%20LG))%0A%20%20%20%20print(%22Coordinates%20of%20mm%20in%20the%20anatomical%20system%3A%5Cn%22%2C%20mml.round(4)%20%2B%200.0)%0A%20%20%20%20print(%22Coordinates%20of%20lm%20in%20the%20anatomical%20system%3A%5Cn%22%2C%20lml.round(4)%20%2B%200.0)%0A%20%20%20%20print(%22Coordinates%20of%20fh%20in%20the%20anatomical%20system%3A%5Cn%22%2C%20fhl.round(4)%20%2B%200.0)%0A%20%20%20%20print(%22Coordinates%20of%20mc%20in%20the%20anatomical%20system%3A%5Cn%22%2C%20mcl.round(4)%20%2B%200.0)%0A%20%20%20%20print(%22Coordinates%20of%20kjc%20in%20the%20anatomical%20system%3A%5Cn%22%2C%20kjcl.round(4)%20%2B%200.0)%0A%20%20%20%20print(%22Coordinates%20of%20ajc%20in%20the%20anatomical%20system%20(origin)%3A%5Cn%22%2C%20ajcl.round(4)%20%2B%200.0)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20results%20read%20like%20a%20description%20of%20the%20leg.%20The%20ankle%20joint%20center%20is%20the%20origin%2C%20%24%5B0%2C0%2C0%5D%24.%20The%20knee%20joint%20center%20lies%20on%20the%20%24y%24%20axis%2C%20at%20%24%5B0%2C%2032.01%2C%200%5D%24%3A%2032%20cm%20up%20the%20leg%2C%20which%20is%20the%20length%20of%20the%20leg%20between%20the%20two%20joint%20centers.%20The%20two%20malleoli%20have%20equal%20and%20opposite%20coordinates%2C%20because%20the%20origin%20is%20their%20midpoint%2C%20and%20they%20lie%20in%20the%20%24yz%24%20plane%20(%24x%20%3D%200%24)%2C%20because%20the%20anterior-posterior%20axis%20was%20built%20perpendicular%20to%20the%20line%20between%20them.%20And%20the%20two%20markers%20at%20the%20knee%20are%203.5%20cm%20apart%20in%20%24x%24%3A%20the%20fibular%20head%20is%20behind%20the%20medial%20condyle.%0A%0A%20%20%20%20Now%20the%20same%20transformation%20with%20the%20transformation%20matrix.%20Let's%20build%20%24%5Cmathbf%7BT_%7BGl%7D%7D%24%2C%20check%20that%20its%20inverse%20has%20the%20form%20given%20above%2C%20and%20check%20that%20it%20is%20not%20orthonormal%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(LG%2C%20RGl%2C%20RlG%2C%20mm%2C%20np)%3A%0A%20%20%20%20TGl%20%3D%20np.eye(4)%0A%20%20%20%20TGl%5B%3A3%2C%20%3A3%5D%20%3D%20RGl%0A%20%20%20%20TGl%5B%3A3%2C%203%5D%20%3D%20LG%0A%20%20%20%20_TlG%20%3D%20np.linalg.inv(TGl)%0A%0A%20%20%20%20print(%22Transformation%20matrix%20TGl%3A%5Cn%22%2C%20TGl)%0A%20%20%20%20print(%22%5CnIts%20inverse%20equals%20%5BRlG%2C%20-RlG%20LG%5D%3F%22%2C%20np.allclose(_TlG%5B%3A3%2C%20%3A3%5D%2C%20RlG)%20and%20np.allclose(_TlG%5B%3A3%2C%203%5D%2C%20-RlG%20%40%20LG))%0A%20%20%20%20print(%22Its%20inverse%20equals%20its%20transpose%3F%22%2C%20np.allclose(_TlG%2C%20TGl.T))%0A%20%20%20%20print(%22%5CnCoordinates%20of%20mm%20in%20the%20anatomical%20system%2C%20with%20the%20transformation%20matrix%3A%22%2C%20(_TlG%20%40%20np.append(mm%2C%201)).round(4)%20%2B%200.0)%0A%20%20%20%20return%20(TGl%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Same%20coordinates%20as%20before%2C%20now%20with%20a%20fourth%20component%20equal%20to%201%2C%20the%20price%20of%20packing%20a%20translation%20into%20a%20matrix%20product.%0A%0A%20%20%20%20**Exercise%205.**%20A%20marker%20is%20placed%20on%20the%20shin%2C%204%20cm%20in%20front%20of%20the%20ankle%20joint%20center%20and%2015%20cm%20up%20the%20leg%3A%20%24%5Cmathbf%7BP_l%7D%20%3D%20%5B4%2C%5C%2C%2015%2C%5C%2C%200%5D%24%20cm%20in%20the%20anatomical%20coordinate%20system%20of%20the%20leg.%20Where%20is%20it%20in%20the%20laboratory%3F%20Calculate%20it%20in%20two%20ways%2C%20with%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20and%20%24%5Cmathbf%7BL_G%7D%24%2C%20and%20with%20%24%5Cmathbf%7BT_%7BGl%7D%7D%24%2C%20and%20explain%20why%20it%20is%20more%20than%204%20cm%20in%20front%20of%20the%20ankle%20joint%20center.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(LG%2C%20RGl%2C%20TGl%2C%20ajc%2C%20mo%2C%20np)%3A%0A%20%20%20%20_Pl%20%3D%20np.array(%5B4%2C%2015%2C%200%5D)%0A%20%20%20%20_PG%20%3D%20LG%20%2B%20RGl%20%40%20_Pl%0A%20%20%20%20_PG_T%20%3D%20(TGl%20%40%20np.append(_Pl%2C%201))%5B%3A3%5D%0A%20%20%20%20_offset%20%3D%20_PG%20-%20ajc%0A%0A%20%20%20%20mo.accordion(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Solution%20to%20Exercise%205%22%3A%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rf%22%22%22%0A%20%20%20%20From%20the%20anatomical%20to%20the%20laboratory%20coordinate%20system%20we%20rotate%20first%20and%20then%20translate%2C%20%24%5Cmathbf%7B%7BP_G%7D%7D%20%3D%20%5Cmathbf%7B%7BL_G%7D%7D%20%2B%20%5Cmathbf%7B%7BR_%7B%7BGl%7D%7D%7D%7D%5C%2C%5Cmathbf%7B%7BP_l%7D%7D%24%3A%0A%0A%20%20%20%20%60P_G%20%3D%20%7B_PG.round(2)%7D%60%20cm%0A%0A%20%20%20%20and%20with%20the%20transformation%20matrix%2C%20%24%5Cmathbf%7B%7BT_%7B%7BGl%7D%7D%7D%7D%5C%2C%5B%5Cmathbf%7B%7BP_l%7D%7D%2C%201%5D%24%20gives%20the%20same%20point%2C%20%60%7B_PG_T.round(2)%7D%60%20cm.%0A%0A%20%20%20%20Relative%20to%20the%20ankle%20joint%20center%20the%20marker%20is%20at%20%60%7B_offset.round(2)%7D%60%20cm%20in%20the%20laboratory%3A%20%7B_offset%5B1%5D%3A.1f%7D%20cm%20higher%20and%20%7B_offset%5B0%5D%3A.1f%7D%20cm%20further%20forward.%20Of%20those%20%7B_offset%5B0%5D%3A.1f%7D%20cm%2C%20%244%20%5Ctimes%20%7BRGl%5B0%2C%200%5D%3A.4f%7D%20%3D%20%7B4%20*%20RGl%5B0%2C%200%5D%3A.2f%7D%24%20cm%20come%20from%20the%20marker%20being%20in%20front%20of%20the%20leg%2C%20and%20%2415%20%5Ctimes%20%7BRGl%5B0%2C%201%5D%3A.4f%7D%20%3D%20%7B15%20*%20RGl%5B0%2C%201%5D%3A.2f%7D%24%20cm%20from%20the%20leg%20itself%2C%20which%20is%20inclined%20forward%3A%20the%20%24%5Cmathbf%7B%7BX%7D%7D%24%20component%20of%20its%20%24y%24%20axis%20is%20%7BRGl%5B0%2C%201%5D%3A.4f%7D.%0A%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20A%20whole%20stride%0A%0A%20%20%20%20Winter's%20example%20is%20a%20single%20instant.%20A%20motion%20capture%20system%20gives%20the%20same%20markers%20at%20every%20frame%2C%20and%20the%20same%20calculation%2C%20repeated%20frame%20by%20frame%2C%20gives%20the%20orientation%20of%20the%20leg%20throughout%20a%20movement.%20Let's%20do%20it%20for%20a%20walking%20trial%20recorded%20in%20our%20laboratory%2C%20in%20the%20file%20%60walk.trc%60%20in%20the%20%60data%60%20folder%20of%20this%20repository%3A%20184%20frames%20at%20150%20Hz%2C%20with%20the%20laboratory's%20%24%5Cmathbf%7BX%7D%24%20axis%20pointing%20in%20the%20direction%20of%20walking%2C%20%24%5Cmathbf%7BY%7D%24%20upwards%20and%20%24%5Cmathbf%7BZ%7D%24%20to%20the%20right.%0A%0A%20%20%20%20A%20%60.trc%60%20file%20is%20a%20tab-separated%20text%20file%20with%20six%20lines%20of%20header%20before%20the%20numbers.%20pandas%20can%20read%20the%20numbers%20directly%2C%20with%20the%20separator%2C%20no%20header%2C%20and%20the%20number%20of%20rows%20to%20skip%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(repo_file)%3A%0A%20%20%20%20import%20pandas%20as%20pd%0A%0A%20%20%20%20_data%20%3D%20pd.read_csv(repo_file(%22data%2Fwalk.trc%22)%2C%20sep%3D%22%5Ct%22%2C%20header%3DNone%2C%20skiprows%3D6)%0A%20%20%20%20_data.iloc%5B%3A5%2C%20%3A8%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20But%20then%20the%20columns%20have%20no%20names.%20The%20names%20of%20the%20markers%20are%20in%20the%20fourth%20line%20of%20the%20file%20and%20the%20coordinates%20in%20the%20fifth%2C%20so%20it%20is%20easier%20to%20read%20the%20header%20first%20and%20the%20numbers%20second.%20The%20function%20%60read_trc%60%2C%20from%20the%20%60functions%60%20folder%2C%20does%20that%2C%20and%20returns%20the%20header%20and%20a%20pandas%20DataFrame%20with%20one%20column%20per%20coordinate%20of%20each%20marker%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(read_trc%2C%20repo_file)%3A%0A%20%20%20%20_h%2C%20walk%20%3D%20read_trc(str(repo_file(%22data%2Fwalk.trc%22))%2C%20fname2%3D%22%22%2C%20dropna%3DFalse%2C%20na%3D0.0%2C%20fmt%3D%22uni%22)%0A%20%20%20%20walk.iloc%5B%3A5%2C%20%3A8%5D%0A%20%20%20%20return%20(walk%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20right%20leg%20carries%20the%20same%20four%20markers%20as%20Winter's%20example%3A%20%60R.Ankle%60%20(lateral%20malleolus)%2C%20%60R.Ankle.Medial%60%2C%20%60R.HF%60%20(fibular%20head)%20and%20%60R.Knee.Medial%60.%20We%20convert%20them%20from%20millimetres%20to%20centimetres%20and%20apply%20Winter's%20definition%20to%20every%20frame%20at%20once%3B%20NumPy's%20cross%20product%20works%20row%20by%20row.%0A%0A%20%20%20%20One%20detail%20needs%20care.%20In%20Winter's%20data%20the%20medial%20malleolus%20has%20the%20larger%20%24z%24%20coordinate%2C%20so%20%24%5Cmathbf%7Bmm%7D%20-%20%5Cmathbf%7Blm%7D%24%20points%20along%20%24%2Bz%24%2C%20and%20%24%5Cmathbf%7By%7D%20%5Ctimes%20(%5Cmathbf%7Bmm%7D%20-%20%5Cmathbf%7Blm%7D)%24%20points%20forward.%20In%20our%20laboratory%20%24%5Cmathbf%7BZ%7D%24%20points%20to%20the%20right%2C%20so%20for%20the%20right%20leg%20it%20is%20the%20*lateral*%20malleolus%20that%20has%20the%20larger%20%24z%24%2C%20and%20we%20must%20use%20%24%5Cmathbf%7Blm%7D%20-%20%5Cmathbf%7Bmm%7D%24%20to%20keep%20the%20%24x%24%20axis%20pointing%20forward.%20It%20is%20the%20same%20left-right%20issue%20as%20for%20the%20femur%20in%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py).%0A%0A%20%20%20%20Each%20frame%20then%20gives%20a%20rotation%20matrix%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%2C%20with%20the%20versors%20as%20rows%2C%20and%20%60euler_angles_from_rot_xyz%60%20turns%20it%20into%20three%20angles%3A%20%24%5Calpha%24%20about%20the%20anterior-posterior%20axis%20%24x%24%2C%20%24%5Cbeta%24%20about%20the%20long%20axis%20%24y%24%2C%20and%20%24%5Cgamma%24%20about%20the%20medio-lateral%20axis%20%24z%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt%2C%20walk)%3A%0A%20%20%20%20_t%20%3D%20walk%5B%22Time%22%5D.to_numpy()%0A%0A%20%20%20%20def%20_marker(name)%3A%0A%20%20%20%20%20%20%20%20return%20walk%5B%5Bname%20%2B%20c%20for%20c%20in%20%22xyz%22%5D%5D.to_numpy()%20%2F%2010%20%20%23%20cm%0A%0A%20%20%20%20_lm%2C%20_mm%20%3D%20_marker(%22R.Ankle%22)%2C%20_marker(%22R.Ankle.Medial%22)%0A%20%20%20%20_fh%2C%20_mc%20%3D%20_marker(%22R.HF%22)%2C%20_marker(%22R.Knee.Medial%22)%0A%20%20%20%20_ajc%2C%20_kjc%20%3D%20(_lm%20%2B%20_mm)%20%2F%202%2C%20(_fh%20%2B%20_mc)%20%2F%202%0A%0A%20%20%20%20_y%20%3D%20_kjc%20-%20_ajc%0A%20%20%20%20_x%20%3D%20np.cross(_y%2C%20_lm%20-%20_mm)%20%20%23%20lateral%20minus%20medial%3A%20right%20leg%2C%20Z%20to%20the%20right%0A%20%20%20%20_z%20%3D%20np.cross(_x%2C%20_y)%0A%20%20%20%20_x%2C%20_y%2C%20_z%20%3D%20(v%20%2F%20np.linalg.norm(v%2C%20axis%3D1%2C%20keepdims%3DTrue)%20for%20v%20in%20(_x%2C%20_y%2C%20_z))%0A%20%20%20%20_RlG%20%3D%20np.stack((_x%2C%20_y%2C%20_z)%2C%20axis%3D1)%20%20%23%20one%20rotation%20matrix%20per%20frame%2C%20versors%20as%20rows%0A%0A%20%20%20%20shank_angles%20%3D%20np.array(%5Beuler_angles_from_rot_xyz(_R)%20for%20_R%20in%20_RlG%5D)%0A%20%20%20%20shank_length%20%3D%20np.linalg.norm(_kjc%20-%20_ajc%2C%20axis%3D1)%0A%0A%20%20%20%20_%2C%20_ax%20%3D%20plt.subplots(figsize%3D(9%2C%204.5))%0A%20%20%20%20_labels%20%3D%20%5Br%22%24%5Calpha%24%2C%20about%20%24x%24%20(anterior-posterior)%22%2C%20r%22%24%5Cbeta%24%2C%20about%20%24y%24%20(long%20axis)%22%2C%20r%22%24%5Cgamma%24%2C%20about%20%24z%24%20(medio-lateral)%22%5D%0A%20%20%20%20for%20_i%2C%20_color%20in%20enumerate(%5B%22tab%3Ared%22%2C%20%22tab%3Agreen%22%2C%20%22tab%3Ablue%22%5D)%3A%0A%20%20%20%20%20%20%20%20_ax.plot(_t%2C%20shank_angles%5B%3A%2C%20_i%5D%2C%20color%3D_color%2C%20linewidth%3D2%2C%20label%3D_labels%5B_i%5D)%0A%20%20%20%20_ax.axhline(0%2C%20color%3D%220.7%22%2C%20linewidth%3D1%2C%20zorder%3D0)%0A%20%20%20%20_ax.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Angle%20%5Bdegrees%5D%22)%0A%20%20%20%20_ax.set_title(%22Orientation%20of%20the%20right%20shank%2C%20xyz%20Cardan%20angles%22)%0A%20%20%20%20_ax.legend(loc%3D%22lower%20right%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20shank_angles%2C%20shank_length%0A%0A%0A%40app.cell%0Adef%20_(shank_angles%2C%20shank_length)%3A%0A%20%20%20%20print(%22Range%20of%20each%20angle%20%5Bdegrees%5D%3A%22)%0A%20%20%20%20for%20_name%2C%20_col%20in%20zip(%5B%22alpha%22%2C%20%22beta%22%2C%20%22gamma%22%5D%2C%20shank_angles.T)%3A%0A%20%20%20%20%20%20%20%20print(f%22%20%20%7B_name%3A5s%7D%3A%20from%20%7B_col.min()%3A6.1f%7D%20to%20%7B_col.max()%3A6.1f%7D%22)%0A%20%20%20%20print(f%22%5CnDistance%20between%20the%20joint%20centers%3A%20from%20%7Bshank_length.min()%3A.2f%7D%20to%20%7Bshank_length.max()%3A.2f%7D%20cm%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20trial%20starts%20with%20the%20right%20leg%20in%20swing%20and%20covers%20the%20following%20stance%20phase.%20The%20largest%20rotation%20is%20%24%5Cgamma%24%2C%20the%20inclination%20of%20the%20shank%20in%20the%20sagittal%20plane%3A%20from%20about%20%24-65%5Eo%24%20in%20swing%2C%20with%20the%20knee%20far%20ahead%20of%20the%20ankle%2C%20to%20about%20%24%2B36%5Eo%24%20around%20heel%20strike%2C%20with%20the%20ankle%20ahead%20of%20the%20knee%2C%20after%20which%20the%20shank%20rotates%20forward%20over%20the%20foot%20during%20stance.%0A%0A%20%20%20%20%24%5Cbeta%24%2C%20the%20rotation%20about%20the%20long%20axis%2C%20stays%20between%20about%20%24-32%5Eo%24%20and%20%24-19%5Eo%24%3A%20the%20shank's%20coordinate%20system%20is%20rotated%20externally%2C%20with%20its%20%24x%24%20axis%20pointing%20forward%20and%20to%20the%20right.%20Part%20of%20the%20reason%20is%20anatomical%3A%20the%20line%20through%20the%20two%20malleoli%20is%20normally%20turned%20outwards%20relative%20to%20the%20axis%20of%20the%20knee%20(external%20tibial%20torsion)%2C%20and%20the%20definition%20we%20used%20takes%20its%20medio-lateral%20direction%20from%20the%20malleoli.%20Part%20is%20the%20posture%20of%20the%20whole%20leg%3A%20these%20angles%20are%20measured%20relative%20to%20the%20laboratory%2C%20so%20any%20outward%20turn%20of%20the%20leg%20relative%20to%20the%20direction%20of%20walking%20adds%20to%20them.%0A%0A%20%20%20%20And%20%24%5Calpha%24%20swings%20by%20about%2045%C2%B0%2C%20from%20%24-27%5Eo%24%20to%20%24%2B18%5Eo%24.%20Is%20the%20shank%20really%20tilting%20sideways%20that%20much%20at%20every%20stride%3F%20It%20is%20not.%20With%20a%20large%20sagittal%20rotation%20applied%20*last*%20and%20a%20coordinate%20system%20turned%20about%20its%20long%20axis%2C%20the%20%24xyz%24%20decomposition%20attributes%20part%20of%20the%20sagittal%20motion%20to%20%24%5Calpha%24%3A%20the%20same%20orientations%2C%20described%20in%20another%20order%2C%20would%20give%20a%20much%20smaller%20frontal%20angle.%20This%20%22cross-talk%22%20between%20angles%20is%20another%20face%20of%20the%20dependence%20on%20the%20sequence%2C%20and%20one%20reason%20why%20the%20flexion%E2%80%93extension%20axis%20is%20placed%20first%20in%20biomechanics.%20Problem%208%20asks%20you%20to%20check%20it.%0A%0A%20%20%20%20Finally%2C%20the%20distance%20between%20the%20two%20joint%20centers%2C%20which%20should%20be%20constant%20for%20a%20rigid%20leg%2C%20varies%20by%20about%201.3%20cm%20during%20the%20trial.%20The%20markers%20move%20on%20the%20skin%2C%20and%20the%20leg%20is%20rigid%20only%20approximately%3B%20see%20%5BDetermination%20of%20a%20coordinate%20system%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fcoordinate_system.py)%20for%20what%20that%20does%20to%20the%20axes.%0A%0A%20%20%20%20**Challenge%202.**%20Add%20a%20horizontal%20line%20at%20the%20angles%20of%20the%20leg%20in%20Winter's%20static%20example%20(calculated%20with%20%60euler_angles_from_rot_xyz(RlG)%60)%20to%20the%20figure.%20Is%20Winter's%20posture%20close%20to%20any%20instant%20of%20this%20stride%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20A%20marker%20hidden%20from%20the%20cameras%0A%0A%20%20%20%20In%20walking%2C%20the%20medial%20malleolus%20marker%20is%20often%20hidden%20from%20the%20cameras%20for%20a%20few%20frames%2C%20when%20the%20other%20leg%20passes%20in%20front%20of%20it.%20The%20transformation%20matrix%20is%20the%20standard%20way%20to%20fill%20such%20a%20gap.%20Three%20other%20markers%20on%20the%20same%20segment%2C%20visible%20throughout%2C%20define%20a%20technical%20coordinate%20system%20at%20every%20frame.%20In%20the%20last%20frame%20before%20the%20gap%2C%20we%20express%20the%20hidden%20marker%20in%20that%20coordinate%20system%2C%20%24%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BT_%7BGl%7D%5E%7B-1%7D%7D%5C%2C%5Cmathbf%7BP_G%7D%24%2C%20once.%20If%20the%20segment%20is%20rigid%2C%20those%20local%20coordinates%20do%20not%20change%2C%20so%20during%20the%20gap%20the%20marker%20is%20wherever%20%24%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BT_%7BGl%7D%7D%5C%2C%5Cmathbf%7BP_l%7D%24%20puts%20it%2C%20frame%20by%20frame.%0A%0A%20%20%20%20Our%20trial%20has%20no%20gap%2C%20which%20is%20convenient%3A%20we%20can%20pretend%20that%20%60R.Ankle.Medial%60%20disappears%20for%200.2%20s%20of%20the%20swing%20phase%2C%20fill%20the%20gap%20from%20%60R.HF%60%2C%20%60R.TT%60%20(on%20the%20tibial%20tuberosity)%20and%20%60R.Ankle%60%2C%20and%20compare%20the%20result%20with%20the%20marker%20that%20was%20actually%20measured.%20The%20technical%20coordinate%20system%20is%20built%20with%20the%20recipe%20of%20the%20basis%20method%2C%20with%20its%20origin%20at%20the%20centroid%20of%20the%20three%20markers%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20transformation_from_markers(m1%2C%20m2%2C%20m3)%3A%0A%20%20%20%20%22%22%22Transformation%20matrices%20T_Gl%20of%20the%20technical%20coordinate%20system%20of%20three%20markers.%0A%0A%20%20%20%20Each%20marker%20is%20an%20array%20of%20positions%2C%20one%20frame%20per%20row.%20The%20first%20axis%20is%0A%20%20%20%20along%20m2%20-%20m1%2C%20the%20second%20is%20perpendicular%20to%20the%20plane%20of%20the%20markers%2C%20the%0A%20%20%20%20third%20completes%20a%20right-handed%20basis%2C%20and%20the%20origin%20is%20the%20centroid%20of%20the%0A%20%20%20%20markers.%20Returns%20one%204x4%20matrix%20per%20frame.%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20v1%20%3D%20m2%20-%20m1%0A%20%20%20%20v2%20%3D%20np.cross(v1%2C%20m3%20-%20m1)%0A%20%20%20%20v3%20%3D%20np.cross(v1%2C%20v2)%0A%20%20%20%20T%20%3D%20np.zeros((len(m1)%2C%204%2C%204))%0A%20%20%20%20T%5B%3A%2C%20%3A3%2C%20%3A3%5D%20%3D%20np.stack(%5Bv%20%2F%20np.linalg.norm(v%2C%20axis%3D1%2C%20keepdims%3DTrue)%20for%20v%20in%20(v1%2C%20v2%2C%20v3)%5D%2C%20axis%3D2)%0A%20%20%20%20T%5B%3A%2C%20%3A3%2C%203%5D%20%3D%20(m1%20%2B%20m2%20%2B%20m3)%20%2F%203%0A%20%20%20%20T%5B%3A%2C%203%2C%203%5D%20%3D%201%0A%20%20%20%20return%20T%0A%0A%0A%40app.function%0Adef%20fill_gap(hidden%2C%20m1%2C%20m2%2C%20m3%2C%20gap%2C%20ref)%3A%0A%20%20%20%20%22%22%22Positions%20of%20the%20marker%20%60hidden%60%20in%20the%20frames%20%60gap%60%2C%20from%20three%20markers%20of%20the%20same%20segment.%0A%0A%20%20%20%20The%20local%20coordinates%20of%20the%20hidden%20marker%20are%20taken%20from%20the%20frame%20%60ref%60.%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20T%20%3D%20transformation_from_markers(m1%2C%20m2%2C%20m3)%0A%20%20%20%20p_local%20%3D%20np.linalg.inv(T%5Bref%5D)%20%40%20np.append(hidden%5Bref%5D%2C%201)%20%20%23%20Global%20to%20local%2C%20once%0A%20%20%20%20return%20(T%5Bgap%5D%20%40%20p_local)%5B%3A%2C%20%3A3%5D%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20after%200.2%20s%20of%20swing%2C%20how%20far%20will%20the%20filled%20marker%20be%20from%20the%20measured%20one%3F%20A%20millimetre%3F%20A%20centimetre%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt%2C%20walk)%3A%0A%20%20%20%20walk_time%20%3D%20walk%5B%22Time%22%5D.to_numpy()%0A%20%20%20%20shank_markers%20%3D%20%7B%0A%20%20%20%20%20%20%20%20_name%3A%20walk%5B%5B_name%20%2B%20_c%20for%20_c%20in%20%22xyz%22%5D%5D.to_numpy()%20%2F%2010%20%20%23%20cm%0A%20%20%20%20%20%20%20%20for%20_name%20in%20%5B%22R.HF%22%2C%20%22R.TT%22%2C%20%22R.Ankle%22%2C%20%22R.Ankle.Medial%22%5D%0A%20%20%20%20%7D%0A%20%20%20%20gap_frames%20%3D%20np.arange(15%2C%2045)%20%20%23%2030%20frames%2C%200.2%20s%20of%20swing%0A%20%20%20%20gap_ref%20%3D%20gap_frames%5B0%5D%20-%201%20%20%23%20the%20last%20frame%20in%20which%20the%20marker%20was%20seen%0A%0A%20%20%20%20_filled%20%3D%20fill_gap(%0A%20%20%20%20%20%20%20%20shank_markers%5B%22R.Ankle.Medial%22%5D%2C%20shank_markers%5B%22R.HF%22%5D%2C%20shank_markers%5B%22R.TT%22%5D%2C%20shank_markers%5B%22R.Ankle%22%5D%2C%0A%20%20%20%20%20%20%20%20gap_frames%2C%20gap_ref%2C%0A%20%20%20%20)%0A%20%20%20%20gap_error%20%3D%2010%20*%20np.linalg.norm(_filled%20-%20shank_markers%5B%22R.Ankle.Medial%22%5D%5Bgap_frames%5D%2C%20axis%3D1)%20%20%23%20mm%0A%0A%20%20%20%20_names%20%3D%20list(shank_markers)%0A%20%20%20%20_changes%20%3D%20%5B%0A%20%20%20%20%20%20%20%20np.ptp(np.linalg.norm(shank_markers%5B_a%5D%20-%20shank_markers%5B_b%5D%2C%20axis%3D1))%0A%20%20%20%20%20%20%20%20for%20_i%2C%20_a%20in%20enumerate(_names)%0A%20%20%20%20%20%20%20%20for%20_b%20in%20_names%5B_i%20%2B%201%20%3A%5D%0A%20%20%20%20%5D%0A%0A%20%20%20%20print(f%22Gap%20from%20%7Bwalk_time%5Bgap_frames%5B0%5D%5D%3A.3f%7D%20to%20%7Bwalk_time%5Bgap_frames%5B-1%5D%5D%3A.3f%7D%20s%2C%20local%20coordinates%20from%20%7Bwalk_time%5Bgap_ref%5D%3A.3f%7D%20s%22)%0A%20%20%20%20print(f%22Error%20of%20the%20filled%20marker%3A%20mean%20%7Bgap_error.mean()%3A.1f%7D%20mm%2C%20largest%20%7Bgap_error.max()%3A.1f%7D%20mm%22)%0A%20%20%20%20print(f%22Largest%20change%20in%20a%20distance%20between%20two%20shank%20markers%20during%20the%20trial%3A%20%7Bmax(_changes)%3A.2f%7D%20cm%22)%0A%0A%20%20%20%20_%2C%20_ax%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20_ax.plot(walk_time%5Bgap_frames%5D%2C%20gap_error%2C%20color%3D%22tab%3Ared%22%2C%20linewidth%3D2%2C%20marker%3D%22o%22%2C%20markersize%3D4)%0A%20%20%20%20_ax.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Error%20%5Bmm%5D%22)%0A%20%20%20%20_ax.set_title(%22Filled%20medial%20malleolus%20marker%20minus%20the%20measured%20one%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20gap_error%2C%20gap_frames%2C%20gap_ref%2C%20shank_markers%2C%20walk_time%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20error%20is%20zero%20at%20the%20reference%20frame%2C%20just%20before%20the%20gap.%20It%20reaches%20about%201%20cm%20within%200.1%20s%2C%20eases%20a%20little%2C%20and%20then%20climbs%20to%20almost%202%20cm%20at%20the%20end%20of%20the%20gap.%20Two%20things%20are%20to%20blame.%20First%2C%20the%20shank%20is%20not%20quite%20rigid%20as%20the%20markers%20see%20it%3A%20the%20markers%20sit%20on%20skin%2C%20which%20moves%20relative%20to%20the%20bone%2C%20and%20the%20distances%20between%20them%2C%20which%20a%20rigid%20body%20would%20keep%20constant%2C%20change%20by%20more%20than%201.5%20cm%20during%20the%20trial.%20The%20further%20the%20leg%20moves%20from%20the%20reference%20frame%2C%20the%20more%20the%20cluster%20has%20deformed.%20Second%2C%20the%20technical%20coordinate%20system%20can%20amplify%20the%20errors%20of%20its%20own%20markers%2C%20which%20is%20what%20the%20next%20exercise%20is%20about.%0A%0A%20%20%20%20In%20practice%2C%20gaps%20are%20filled%20from%20the%20frames%20closest%20to%20them%2C%20often%20from%20both%20ends%20of%20the%20gap%20at%20once%2C%20and%20a%20filled%20marker%20is%20always%20an%20estimate.%0A%0A%20%20%20%20**Exercise%206.**%20In%20the%20technical%20coordinate%20system%20above%2C%20the%20first%20axis%20goes%20from%20%60R.HF%60%20to%20%60R.TT%60%2C%20two%20markers%20only%20about%208%20cm%20apart%2C%20both%20near%20the%20knee.%20Build%20it%20instead%20with%20the%20first%20axis%20along%20the%20leg%2C%20from%20%60R.HF%60%20to%20%60R.Ankle%60%2C%20about%2036%20cm%20apart%2C%20keeping%20the%20same%20three%20markers%2C%20and%20fill%20the%20same%20gap.%20Before%20computing%2C%20predict%3A%20can%20the%20change%20matter%20at%20all%2C%20since%20the%20three%20markers%20are%20the%20same%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(gap_error%2C%20gap_frames%2C%20gap_ref%2C%20mo%2C%20np%2C%20plt%2C%20shank_markers%2C%20walk_time)%3A%0A%20%20%20%20_filled%20%3D%20fill_gap(%0A%20%20%20%20%20%20%20%20shank_markers%5B%22R.Ankle.Medial%22%5D%2C%20shank_markers%5B%22R.HF%22%5D%2C%20shank_markers%5B%22R.Ankle%22%5D%2C%20shank_markers%5B%22R.TT%22%5D%2C%0A%20%20%20%20%20%20%20%20gap_frames%2C%20gap_ref%2C%0A%20%20%20%20)%0A%20%20%20%20_error%20%3D%2010%20*%20np.linalg.norm(_filled%20-%20shank_markers%5B%22R.Ankle.Medial%22%5D%5Bgap_frames%5D%2C%20axis%3D1)%20%20%23%20mm%0A%20%20%20%20_T%20%3D%20transformation_from_markers(shank_markers%5B%22R.HF%22%5D%2C%20shank_markers%5B%22R.TT%22%5D%2C%20shank_markers%5B%22R.Ankle%22%5D)%0A%20%20%20%20_p_local%20%3D%20(np.linalg.inv(_T%5Bgap_ref%5D)%20%40%20np.append(shank_markers%5B%22R.Ankle.Medial%22%5D%5Bgap_ref%5D%2C%201))%5B%3A3%5D%0A%20%20%20%20_lever%20%3D%20np.linalg.norm(_p_local)%20%20%23%20cm%2C%20distance%20of%20the%20hidden%20marker%20from%20the%20origin%0A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20_ax.plot(walk_time%5Bgap_frames%5D%2C%20gap_error%2C%20color%3D%22tab%3Ared%22%2C%20linewidth%3D2%2C%20label%3D%22first%20axis%20R.HF%20to%20R.TT%20(8%20cm)%22)%0A%20%20%20%20_ax.plot(walk_time%5Bgap_frames%5D%2C%20_error%2C%20color%3D%22tab%3Ablue%22%2C%20linewidth%3D2%2C%20label%3D%22first%20axis%20R.HF%20to%20R.Ankle%20(36%20cm)%22)%0A%20%20%20%20_ax.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Error%20%5Bmm%5D%22)%0A%20%20%20%20_ax.legend(loc%3D%22upper%20left%22)%0A%20%20%20%20plt.tight_layout()%0A%0A%20%20%20%20mo.accordion(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Solution%20to%20Exercise%206%22%3A%20mo.vstack(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22It%20matters%20a%20lot.%20With%20the%20first%20axis%20along%20the%20leg%2C%20the%20mean%20error%20drops%20from%20%7Bgap_error.mean()%3A.1f%7D%20to%20%7B_error.mean()%3A.1f%7D%20mm%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20f%22and%20the%20largest%20from%20%7Bgap_error.max()%3A.1f%7D%20to%20%7B_error.max()%3A.1f%7D%20mm.%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_fig%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22With%20noise-free%20markers%2C%20the%20three%20markers%20would%20define%20the%20same%20coordinate%20system%20in%20any%20order.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22With%20real%20markers%20they%20do%20not%2C%20because%20the%20first%20axis%20is%20taken%20exactly%20along%20the%20first%20pair%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22and%20the%20same%20error%20of%20a%20few%20millimetres%20tilts%20a%20vector%208%20cm%20long%20four%20to%20five%20times%20more%20than%20a%20vector%2036%20cm%20long.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20f%22The%20hidden%20marker%20is%20%7B_lever%3A.0f%7D%20cm%20from%20the%20origin%20of%20the%20technical%20coordinate%20system%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20f%22so%20every%20tenth%20of%20a%20degree%20of%20error%20in%20the%20axes%20moves%20it%20by%20%7B10%20*%20_lever%20*%20np.radians(0.1)%3A.1f%7D%20mm.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22In%20the%20first%20half%20of%20the%20gap%20the%20two%20curves%20agree%3A%20that%20part%20of%20the%20error%20comes%20from%20the%20skin%2C%20and%20no%20choice%20of%20axes%20removes%20it.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22The%20late%20climb%20came%20from%20the%20short%20first%20axis.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22The%20rule%20from%20%5BDetermination%20of%20a%20coordinate%20system%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fcoordinate_system.py)%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22applies%3A%20build%20the%20first%20axis%20from%20the%20two%20markers%20that%20are%20farthest%20apart.%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Checkpoint%20questions%0A%0A%20%20%20%20Pause%20here%20before%20the%20problems.%0A%0A%20%20%20%201.%20Go%20back%20to%20your%20sketches%20from%20Challenge%200%20and%20to%20Codman's%20paradox.%20In%20one%20sentence%20each%2C%20explain%20both%20with%20rotation%20matrices.%0A%20%20%20%202.%20You%20are%20given%20a%203%C3%973%20matrix%20and%20told%20it%20is%20a%20rotation%20matrix.%20Name%20two%20checks%20you%20would%20make%20before%20believing%20it.%0A%20%20%20%203.%20A%20paper%20reports%20%22the%20knee%20was%20flexed%2040%C2%B0%2C%20abducted%205%C2%B0%20and%20rotated%2010%C2%B0%22%20without%20stating%20the%20sequence.%20What%20is%20missing%2C%20and%20how%20much%20could%20it%20matter%3F%0A%20%20%20%204.%20Why%20can't%20you%20obtain%20the%20orientation%20of%20the%20shank%20relative%20to%20the%20thigh%20by%20subtracting%20the%20Euler%20angles%20of%20the%20two%20segments%3F%0A%20%20%20%205.%20You%20analyse%20a%20movement%20in%20which%20one%20segment%20approaches%2090%C2%B0%20in%20the%20second%20rotation%20of%20your%20sequence.%20What%20do%20you%20expect%20to%20see%20in%20the%20other%20two%20angles%2C%20and%20what%20would%20you%20do%20about%20it%3F%0A%20%20%20%206.%20The%20transformation%20matrix%20packs%20a%20rotation%20and%20a%20translation%20together.%20Why%20is%20its%20inverse%20not%20its%20transpose%2C%20when%20the%20inverse%20of%20the%20rotation%20matrix%20is%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Problems%0A%0A%20%20%20%201.%20For%20the%20example%20of%20how%20the%20order%20of%20rotations%20of%20a%20rigid%20body%20affects%20its%20orientation%2C%20shown%20in%20a%20figure%20above%2C%20deduce%20the%20rotation%20matrices%20for%20each%20of%20the%204%20cases%20shown%20in%20the%20figure.%20For%20the%20first%20two%20cases%2C%20deduce%20the%20rotation%20matrices%20from%20the%20Global%20to%20the%20local%20coordinate%20system%2C%20and%20for%20the%20other%20two%2C%20the%20rotation%20matrices%20from%20the%20local%20to%20the%20Global%20coordinate%20system.%0A%0A%20%20%20%202.%20Consider%20the%20data%20from%20problem%205%20in%20the%20notebook%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py)%2C%20where%20the%20following%20anatomical%20landmark%20positions%20are%20given%20(units%20in%20meters)%3A%20RASIS%3D%5B0.5%2C%200.8%2C%200.4%5D%2C%20LASIS%3D%5B0.55%2C%200.78%2C%200.1%5D%2C%20RPSIS%3D%5B0.3%2C%200.85%2C%200.2%5D%2C%20and%20LPSIS%3D%5B0.29%2C%200.78%2C%200.3%5D.%20Deduce%20the%20rotation%20matrices%20for%20the%20Global%20to%20anatomical%20coordinate%20system%20and%20for%20the%20anatomical%20to%20Global%20coordinate%20system.%0A%0A%20%20%20%203.%20For%20the%20data%20from%20the%20example%20with%20actual%20motion%20analysis%20data%2C%20calculate%20the%20Cardan%20angles%20using%20the%20%24zxy%24%20sequence%20for%20the%20orientation%20of%20the%20leg%20with%20respect%20to%20the%20laboratory%20(but%20remember%20that%20the%20letters%20chosen%20to%20refer%20to%20axes%20are%20arbitrary%3B%20what%20matters%20is%20the%20directions%20they%20represent).%0A%0A%20%20%20%204.%20Write%20down%20the%204%C3%974%20matrices%20for%20each%20of%20the%20following%20(adapted%20from%20a%20%5Bcomputer%20graphics%20exercise%20sheet%5D(https%3A%2F%2Fweb.archive.org%2Fweb%2F20200224231232%2Fhttp%3A%2F%2Fwww.eecs.qmul.ac.uk%2F~sgg%2Fcg%2FExers%2Ftransformations_ex.html)%20of%20Queen%20Mary%20University%20of%20London)%3A%3Cbr%3E%0A%20%20%20%20%20%20%20a.%20To%20translate%20by%20the%20vector%20(1%2C%202%2C%203).%3Cbr%3E%0A%20%20%20%20%20%20%20b.%20To%20scale%20with%20respect%20to%20the%20origin%20by%20the%20amount%20(2%2C%204%2C%206).%3Cbr%3E%0A%20%20%20%20%20%20%20c.%20To%20rotate%20around%20the%20z%20axis%20by%2045%20degrees%20(note%20that%20sin%2045%C2%B0%20%3D%20cos%2045%C2%B0%20%3D%201%2F%E2%88%9A2).%3Cbr%3E%0A%20%20%20%20%20%20%20d.%20To%20rotate%20around%20the%20x%20axis%20by%2045%20degrees.%0A%0A%20%20%20%205.%20Compute%20the%20variation%20of%20Codman's%20movement%20from%20Guiding%20question%200.2%3A%20starting%20from%20the%20arm%20hanging%20at%20the%20side%2C%20abduct%20the%20arm%2090%C2%B0%20in%20the%20frontal%20plane%2C%20then%20swing%20it%20horizontally%2090%C2%B0%20to%20the%20front%2C%20then%20lower%20it%2090%C2%B0%20in%20front%20of%20the%20body%20to%20the%20side.%20Write%20each%20movement%20as%20a%20rotation%20about%20a%20fixed%20axis%2C%20with%20its%20sign%2C%20and%20find%20where%20the%20palm%20faces%20at%20the%20end.%20What%20single%20rotation%20is%20equivalent%20to%20the%20whole%20sequence%3F%0A%0A%20%20%20%206.%20For%20the%20%24zxz%24%20sequence%2C%20repeat%20the%20analysis%20of%20the%20section%20%22How%20close%20is%20too%20close%3F%22%3A%20find%20the%20value%20of%20%24%5Cbeta%24%20at%20which%20the%20sequence%20locks%2C%20write%20a%20function%20that%20computes%20the%20three%20%24zxz%24%20angles%20from%20a%20rotation%20matrix%2C%20and%20show%20how%20the%20errors%20in%20the%20angles%20grow%20near%20the%20lock.%0A%0A%20%20%20%207.%20The%20coordinate%20system%20of%20the%20thigh%20is%20rotated%20from%20the%20laboratory%20by%20the%20%24xyz%24%20Euler%20angles%20(5%C2%B0%2C%2010%C2%B0%2C%2030%C2%B0)%2C%20and%20that%20of%20the%20shank%20by%20(5%C2%B0%2C%2015%C2%B0%2C%20%E2%88%9220%C2%B0).%20Calculate%20the%20rotation%20matrix%20of%20the%20shank%20relative%20to%20the%20thigh%20and%20its%20%24xyz%24%20Euler%20angles.%20Are%20they%20the%20differences%20between%20the%20angles%20of%20the%20two%20segments%3F%0A%0A%20%20%20%208.%20Repeat%20the%20analysis%20of%20the%20whole%20stride%20with%20the%20%24zxy%24%20sequence%2C%20which%20puts%20the%20rotation%20about%20the%20medio-lateral%20axis%20first.%20Use%20%60euler_rotmat%60%20to%20obtain%20the%20algebraic%20matrix%2C%20derive%20the%20formulas%20for%20the%20three%20angles%2C%20and%20plot%20them.%20Compare%20the%20frontal-plane%20angle%20with%20%24%5Calpha%24%20of%20the%20%24xyz%24%20sequence%2C%20and%20explain%20the%20difference.%0A%0A%20%20%20%209.%20Euler's%20rotation%20theorem%20also%20works%20the%20other%20way%20round%3A%20a%20rotation%20by%20the%20angle%20%24%5Ctheta%24%20about%20the%20axis%20%24%5Chat%7B%5Cmathbf%7Bn%7D%7D%24%20has%20the%20rotation%20matrix%20%24%5Cmathbf%7BR%7D%20%3D%20%5Cmathbf%7BI%7D%20%2B%20%5Csin%5Ctheta%5C%2C%5Cmathbf%7BK%7D%20%2B%20(1%20-%20%5Ccos%5Ctheta)%5C%2C%5Cmathbf%7BK%7D%5E2%24%20(Rodrigues'%20formula)%2C%20where%20%24%5Cmathbf%7BK%7D%24%20is%20the%20matrix%20for%20which%20%24%5Cmathbf%7BK%7D%5Cmathbf%7Bv%7D%20%3D%20%5Chat%7B%5Cmathbf%7Bn%7D%7D%20%5Ctimes%20%5Cmathbf%7Bv%7D%24%20for%20any%20vector%20%24%5Cmathbf%7Bv%7D%24.%20Write%20%24%5Cmathbf%7BK%7D%24%2C%20implement%20the%20formula%20as%20a%20function%2C%20and%20check%20it%20against%20%60axis_angle%60%20with%20the%20rotation%20of%20%2430%5Eo%24%2C%20%2445%5Eo%24%20and%20%2460%5Eo%24%20about%20%24%5Cmathbf%7BX%7D%24%2C%20%24%5Cmathbf%7BY%7D%24%20and%20%24%5Cmathbf%7BZ%7D%24%20from%20the%20section%20%22One%20rotation%20is%20enough%22.%0A%0A%20%20%20%2010.%20Expand%20%24%5Cmathbf%7BR_X%7D(%5Ctheta)%24%20and%20%24%5Cmathbf%7BR_Z%7D(%5Ctheta)%24%20to%20second%20order%20in%20%24%5Ctheta%24%20(%24%5Ccos%5Ctheta%20%5Capprox%201%20-%20%5Ctheta%5E2%2F2%24%2C%20%24%5Csin%5Ctheta%20%5Capprox%20%5Ctheta%24)%20and%20show%20that%20the%20two%20orders%20of%20the%20rotations%20differ%20by%20a%20rotation%20of%20approximately%20%24%5Ctheta%5E2%24%20radians%20about%20the%20%24%5Cmathbf%7BY%7D%24%20axis%2C%20as%20the%20table%20in%20%22How%20much%20does%20the%20order%20matter%3F%22%20suggests.%20Why%20does%20the%20axis%20of%20the%20difference%20tilt%20away%20from%20%24%5Cmathbf%7BY%7D%24%20for%20larger%20angles%3F%0A%0A%20%20%20%2011.%20Using%20the%20four%20pelvic%20markers%20of%20%60walk.trc%60%20(%60R.ASIS%60%2C%20%60L.ASIS%60%2C%20%60R.PSIS%60%20and%20%60L.PSIS%60)%20and%20the%20VAKHUM%20convention%20of%20Problem%202%2C%20calculate%20the%20anatomical%20coordinate%20system%20of%20the%20pelvis%20at%20every%20frame%20of%20the%20stride%2C%20and%20plot%20its%20%24xyz%24%20Cardan%20angles%20relative%20to%20the%20laboratory.%20Which%20angle%20varies%20most%2C%20and%20by%20how%20much%3F%20Is%20the%20pelvis%20close%20to%20gimbal%20lock%20at%20any%20moment%3F%0A%0A%20%20%20%2012.%20The%20right%20thigh%20in%20%60walk.trc%60%20carries%20the%20markers%20%60R.GTR%60%20(greater%20trochanter)%2C%20%60R.Knee%60%20(lateral%20epicondyle)%20and%20%60R.Knee.Medial%60.%20Define%20a%20coordinate%20system%20for%20the%20thigh%20in%20the%20same%20way%20as%20for%20the%20shank%20in%20the%20section%20%22A%20whole%20stride%22%20(the%20%24y%24%20axis%20from%20the%20knee%20joint%20center%2C%20midway%20between%20the%20two%20knee%20markers%2C%20to%20the%20greater%20trochanter%2C%20and%20a%20temporary%20medio-lateral%20axis%20from%20%60R.Knee.Medial%60%20to%20%60R.Knee%60).%20Calculate%20the%20rotation%20matrix%20of%20the%20shank%20relative%20to%20the%20thigh%20at%20every%20frame%2C%20and%20use%20%60axis_angle%60%20to%20plot%20the%20total%20rotation%20of%20the%20knee%20during%20the%20stride.%20When%20is%20it%20largest%3F%20Why%20is%20it%20not%20zero%20when%20the%20knee%20is%20at%20its%20straightest%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Final%20answers%20to%20the%20problems%0A%0A%20%20%20%201.%20For%20positive%2090%C2%B0%20turns%20and%20the%20figure%E2%80%99s%20four%20rows%3A%20fixed%20X%20then%20Y%2C%20global-to-local%20%24%5B%5B0%2C0%2C-1%5D%2C%5B1%2C0%2C0%5D%2C%5B0%2C-1%2C0%5D%5D%24%3B%20fixed%20Y%20then%20X%2C%20global-to-local%20%24%5B%5B0%2C1%2C0%5D%2C%5B0%2C0%2C1%5D%2C%5B1%2C0%2C0%5D%5D%24%3B%20local%20x%20then%20y%2C%20local-to-global%20%24%5B%5B0%2C0%2C1%5D%2C%5B1%2C0%2C0%5D%2C%5B0%2C1%2C0%5D%5D%24%3B%20local%20y%20then%20x%2C%20local-to-global%20%24%5B%5B0%2C1%2C0%5D%2C%5B0%2C0%2C-1%5D%2C%5B-1%2C0%2C0%5D%5D%24.%0A%20%20%20%202.%20Global-to-pelvis%20%24R%3D%5B%5B0.980530%2C-0.098327%2C0.169977%5D%2C%5B0.107934%2C0.992988%2C-0.048210%5D%2C%5B-0.164045%2C0.065618%2C0.984268%5D%5D%24.%20Pelvis-to-global%20is%20%24R%5ET%24.%0A%20%20%20%203.%20Intrinsic%20%24zxy%24%20angles%20for%20the%20static%20leg%20example%20are%20approximately%20%24(-6.92713%2C-3.08021%2C-1.66623)%5E%5Ccirc%24.%0A%20%20%20%204.%20(a)%20%24%5B%5B1%2C0%2C0%2C1%5D%2C%5B0%2C1%2C0%2C2%5D%2C%5B0%2C0%2C1%2C3%5D%2C%5B0%2C0%2C0%2C1%5D%5D%24.%20(b)%20%24%5Coperatorname%7Bdiag%7D(2%2C4%2C6%2C1)%24.%20With%20%24q%3D1%2F%5Csqrt2%24%3A%20(c)%20%24%5B%5Bq%2C-q%2C0%2C0%5D%2C%5Bq%2Cq%2C0%2C0%5D%2C%5B0%2C0%2C1%2C0%5D%2C%5B0%2C0%2C0%2C1%5D%5D%24%3B%20(d)%20%24%5B%5B1%2C0%2C0%2C0%5D%2C%5B0%2Cq%2C-q%2C0%5D%2C%5B0%2Cq%2Cq%2C0%5D%2C%5B0%2C0%2C0%2C1%5D%5D%24.%0A%20%20%20%205.%20With%20%24X%24%20anterior%2C%20%24Y%24%20upward%20and%20%24Z%24%20right%3A%20%24R_Z(-90%5E%5Ccirc)R_Y(90%5E%5Ccirc)R_X(-90%5E%5Ccirc)%3DR_Y(90%5E%5Ccirc)%24.%20The%20right%20palm%20ends%20facing%20backward%2C%20opposite%20to%20the%20original%20sequence%E2%80%99s%20result.%0A%20%20%20%206.%20%24zxz%24%20locks%20at%20middle%20angle%20%24%5Cbeta%3D0%24%20or%20%24%5Cpi%24.%20For%20local-to-global%20matrix%20%24A%24%20away%20from%20the%20lock%2C%20%24%5Cbeta%3D%5Carccos%20A_%7B22%7D%24%2C%20%24%5Calpha%3D%5Coperatorname%7Batan2%7D(A_%7B02%7D%2C-A_%7B12%7D)%24%2C%20%24%5Cgamma%3D%5Coperatorname%7Batan2%7D(A_%7B20%7D%2CA_%7B21%7D)%24.%20Angle-error%20amplification%20scales%20with%20%241%2F%7C%5Csin%5Cbeta%7C%24%3B%20at%20the%20lock%20the%20individual%20outer%20angles%20are%20not%20unique.%0A%20%20%20%207.%20Shank-to-thigh%20rotation%20is%20approximately%20%24%5B%5B0.639691%2C0.764917%2C0.075479%5D%2C%5B-0.764257%2C0.643438%2C-0.043578%5D%2C%5B-0.081900%2C-0.029809%2C0.996195%5D%5D%24.%20Intrinsic%20xyz%20angles%20are%20%24(2.50477%2C4.32875%2C-50.09468)%5E%5Ccirc%24%3B%20they%20are%20not%20the%20componentwise%20differences.%0A%20%20%20%208.%20For%20local-to-global%20%24A%24%2C%20%24%5Cbeta%3D%5Carcsin%20A_%7B21%7D%24%2C%20%24%5Calpha%3D%5Coperatorname%7Batan2%7D(-A_%7B01%7D%2CA_%7B11%7D)%24%2C%20%24%5Cgamma%3D%5Coperatorname%7Batan2%7D(-A_%7B20%7D%2CA_%7B22%7D)%24.%20The%20stride%20ranges%20in%20z%2Cx%2Cy%20order%20are%20approximately%20%5B%E2%88%9258.545%2C29.879%5D%C2%B0%2C%20%5B%E2%88%921.855%2C6.236%5D%C2%B0%2C%20%5B%E2%88%9235.699%2C%E2%88%9220.707%5D%C2%B0.%20The%20frontal%20excursion%20is%20much%20smaller%20than%20in%20xyz%20because%20the%20decomposition%20assigns%20rotations%20differently.%0A%20%20%20%209.%20%24K%3D%5B%5B0%2C-n_z%2Cn_y%5D%2C%5Bn_z%2C0%2C-n_x%5D%2C%5B-n_y%2Cn_x%2C0%5D%5D%24%3B%20%60I%20%2B%20sin(theta)*K%20%2B%20(1-cos(theta))*(K%40K)%60%20reproduces%20the%20same%20axis-angle%20rotation%20to%20numerical%20precision.%0A%20%20%20%2010.%20The%20leading%20order%20difference%20is%20a%20rotation%20of%20magnitude%20%24%5Ctheta%5E2%24%20about%20Y%2C%20with%20sign%20determined%20by%20the%20order%20used%20for%20comparison.%20Higher-order%20commutator%20terms%20add%20X%20and%20Z%20components%20at%20finite%20angles%2C%20tilting%20the%20equivalent%20axis.%0A%20%20%20%2011.%20Pelvis%20xyz%20ranges%20are%20about%20%5B%E2%88%928.887%2C3.463%5D%C2%B0%2C%20%5B%E2%88%925.608%2C9.246%5D%C2%B0%2C%20%5B%E2%88%924.781%2C1.701%5D%C2%B0.%20The%20Y%20angle%20varies%20most%2C%20by%2014.854%C2%B0%3B%20its%20distance%20from%20%C2%B190%C2%B0%20confirms%20that%20this%20recording%20is%20far%20from%20the%20xyz%20lock.%0A%20%20%20%2012.%20Total%20relative%20rotation%20ranges%20approximately%2019.569%E2%80%9369.987%C2%B0%2C%20largest%20at%20zero-based%20frame%2019%2C%20time%200.127%20s.%20Its%20nonzero%20minimum%20reflects%20the%20anatomical%2Ftechnical%20axis%20definitions%2C%20three-dimensional%20rotation%20and%20marker%2Fsoft-tissue%20effects%3B%20it%20is%20not%20a%20pure%20clinical%20flexion%20angle.%0A%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo%2C%20np%2C%20plt%2C%20walk%2C%20walk_time)%3A%0A%20%20%20%20def%20_marker(_name)%3A%0A%20%20%20%20%20%20%20%20return%20walk%5B%5B_name%2B_c%20for%20_c%20in%20%22xyz%22%5D%5D.to_numpy()%2F10%0A%20%20%20%20def%20_unit(_v)%3A%0A%20%20%20%20%20%20%20%20return%20_v%2Fnp.linalg.norm(_v%2Caxis%3D1%2Ckeepdims%3DTrue)%0A%20%20%20%20_lm%2C_mm%2C_fh%2C_mc%3D%5B_marker(_n)%20for%20_n%20in%20%5B%22R.Ankle%22%2C%22R.Ankle.Medial%22%2C%22R.HF%22%2C%22R.Knee.Medial%22%5D%5D%0A%20%20%20%20_y%3D_unit((_fh%2B_mc-_lm-_mm)%2F2)%3B_x%3D_unit(np.cross(_y%2C_lm-_mm))%3B_z%3Dnp.cross(_x%2C_y)%0A%20%20%20%20_Bs%3Dnp.stack(%5B_x%2C_y%2C_z%5D%2Caxis%3D1)%0A%20%20%20%20_zxy%3Dnp.degrees(np.c_%5Bnp.arctan2(-_Bs%5B%3A%2C1%2C0%5D%2C_Bs%5B%3A%2C1%2C1%5D)%2Cnp.arcsin(np.clip(_Bs%5B%3A%2C1%2C2%5D%2C-1%2C1))%2Cnp.arctan2(-_Bs%5B%3A%2C0%2C2%5D%2C_Bs%5B%3A%2C2%2C2%5D)%5D)%0A%20%20%20%20_ra%2C_la%2C_rp%2C_lp%3D%5B_marker(_n)%20for%20_n%20in%20%5B%22R.ASIS%22%2C%22L.ASIS%22%2C%22R.PSIS%22%2C%22L.PSIS%22%5D%5D%0A%20%20%20%20_z%3D_unit(_ra-_la)%3B_y%3D_unit(np.cross(_z%2C(_ra%2B_la-_rp-_lp)%2F2))%3B_x%3Dnp.cross(_y%2C_z)%0A%20%20%20%20_Bp%3Dnp.stack(%5B_x%2C_y%2C_z%5D%2Caxis%3D1)%0A%20%20%20%20_pq%3Dnp.array(%5Beuler_angles_from_rot_xyz(_R)%20for%20_R%20in%20_Bp%5D)%0A%20%20%20%20_knee%3D(_marker(%22R.Knee%22)%2B_marker(%22R.Knee.Medial%22))%2F2%0A%20%20%20%20_y%3D_unit(_marker(%22R.GTR%22)-_knee)%3B_x%3D_unit(np.cross(_y%2C_marker(%22R.Knee%22)-_marker(%22R.Knee.Medial%22)))%3B_z%3Dnp.cross(_x%2C_y)%0A%20%20%20%20_Bt%3Dnp.stack(%5B_x%2C_y%2C_z%5D%2Caxis%3D1)%3B_rel%3D_Bt%40np.swapaxes(_Bs%2C-1%2C-2)%0A%20%20%20%20_angle%3Dnp.degrees(np.arccos(np.clip((np.trace(_rel%2Caxis1%3D1%2Caxis2%3D2)-1)%2F2%2C-1%2C1)))%0A%20%20%20%20_fig%2C_ax%3Dplt.subplots(3%2C1%2Cfigsize%3D(9%2C9)%2Csharex%3DTrue)%0A%20%20%20%20_ax%5B0%5D.plot(walk_time%2C_zxy)%3B_ax%5B0%5D.legend(%5B%22z%22%2C%22x%22%2C%22y%22%5D)%3B_ax%5B0%5D.set(ylabel%3D%22Shank%20zxy%20%5Bdeg%5D%22)%0A%20%20%20%20_ax%5B1%5D.plot(walk_time%2C_pq)%3B_ax%5B1%5D.legend(%5B%22x%22%2C%22y%22%2C%22z%22%5D)%3B_ax%5B1%5D.set(ylabel%3D%22Pelvis%20xyz%20%5Bdeg%5D%22)%0A%20%20%20%20_ax%5B2%5D.plot(walk_time%2C_angle)%3B_ax%5B2%5D.set(xlabel%3D%22Time%20%5Bs%5D%22%2Cylabel%3D%22Knee%20total%20rotation%20%5Bdeg%5D%22)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_problem_plot%20%3D%20mo.accordion(%7B%22Final%20stride%20plots%20%E2%80%94%20Problems%208%2C%2011%20and%2012%22%3Amo.as_html(_fig)%7D%2Cexpanded%3DFalse)%0A%20%20%20%20plt.close(_fig)%0A%20%20%20%20_problem_plot%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Go%20deeper%0A%0A%20%20%20%20-%20Read%20pages%201136%E2%80%931164%20of%20chapter%2021%20of%20%5BRuina%20and%20Pratap's%20book%5D(https%3A%2F%2Fruina.tam.cornell.edu%2FBook%2Findex.html)%2C%20an%20elementary%20introduction%20to%203D%20rigid-body%20dynamics.%0A%20%20%20%20-%20%5BRotation%20matrix%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FRotation_matrix)%20and%20%5BEuler%20angles%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FEuler_angles)%20on%20Wikipedia.%0A%20%20%20%20-%20%5BRigid-body%20transformations%20in%20a%20plane%20(2D)%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_2d.py)%3A%20the%20two-dimensional%20version%20of%20this%20notebook.%0A%20%20%20%20-%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py)%20and%20%5BDetermination%20of%20a%20coordinate%20system%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fcoordinate_system.py)%3A%20how%20the%20coordinate%20systems%20related%20by%20these%20matrices%20are%20built%20from%20markers.%0A%20%20%20%20-%20%5BAngular%20velocity%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fangular_velocity_3d.py)%3A%20what%20comes%20after%20orientation.%0A%0A%20%20%20%20%23%23%23%20Video%20lectures%20on%20the%20Internet%0A%0A%20%20%20%20-%20%5BRotation%20in%20R3%20around%20the%20x-axis%5D(https%3A%2F%2Fwww.khanacademy.org%2Fmath%2Flinear-algebra%2Fmatrix-transformations%2Flin-trans-examples%2Fv%2Frotation-in-r3-around-the-x-axis)%20-%20Khan%20Academy%0A%20%20%20%20-%20%5BModern%20Robotics%2C%20Chapter%203.2.1%3A%20Rotation%20Matrices%20(Part%201%20of%202)%5D(https%3A%2F%2Fyoutu.be%2FOZucG1DY_sY)%20-%20Northwestern%20Robotics%0A%20%20%20%20-%20%5BRotations%20in%203D%5D(https%3A%2F%2Fyoutu.be%2Fwg9bI8-Qx2Q)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Optional%20assignments%20from%20the%20original%20sources%0A%0A%20%20%20%20These%20original%20reading%20assignments%20remain%20available%20for%20further%20study.%20Their%20full%20statements%20and%20source-specific%20answer%20keys%20are%20external%20to%20this%20guide.%0A%0A%20%20%20%20-%20Solve%20the%20first%20two%20problems%20of%20%5Bthis%20homework%20assignment%5D(https%3A%2F%2Fweb.archive.org%2Fweb%2F20240420193536%2Fhttps%3A%2F%2Frrg.utk.edu%2Fresources%2FBME473%2Fassignments%2FBME473_homework_3.pdf)%20(BME%20473%2C%20University%20of%20Tennessee).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20References%0A%0A%20%20%20%20-%20Corke%20P%20(2011)%20%5BRobotics%2C%20Vision%20and%20Control%3A%20Fundamental%20Algorithms%20in%20MATLAB%5D(https%3A%2F%2Fpetercorke.com%2FRVC%2F).%20Springer-Verlag%20Berlin.%0A%0A%20%20%20%20-%20Grood%20ES%2C%20Suntay%20WJ%20(1983)%20%5BA%20joint%20coordinate%20system%20for%20the%20clinical%20description%20of%20three-dimensional%20motions%3A%20application%20to%20the%20knee%5D(https%3A%2F%2Fdoi.org%2F10.1115%2F1.3138397).%20Journal%20of%20Biomechanical%20Engineering%2C%20105(2)%2C%20136%E2%80%93144.%0A%0A%20%20%20%20-%20%5BMaths%20-%20Euler%20Angles%5D(http%3A%2F%2Fwww.euclideanspace.com%2Fmaths%2Fgeometry%2Frotations%2Feuler%2F).%0A%0A%20%20%20%20-%20Murray%20RM%2C%20Li%20Z%2C%20Sastry%20SS%20(1994)%20%5BA%20Mathematical%20Introduction%20to%20Robotic%20Manipulation%5D(http%3A%2F%2Fwww.cds.caltech.edu%2F~murray%2Fmlswiki%2Findex.php%2FMain_Page).%20Boca%20Raton%2C%20CRC%20Press.%0A%0A%20%20%20%20-%20Politti%20JC%2C%20Goroso%20G%2C%20Valentinuzzi%20ME%2C%20Bravo%20O%20(1998)%20%5BCodman's%20paradox%20of%20the%20arm%20rotations%20is%20not%20a%20paradox%3A%20mathematical%20validation%5D(https%3A%2F%2Fdoi.org%2F10.1016%2FS1350-4533(98)00020-4).%20Medical%20Engineering%20%26%20Physics%2C%2020(4)%2C%20257%E2%80%93260.%0A%0A%20%20%20%20-%20Rade%20D%20(2017)%20%5BCinem%C3%A1tica%20e%20Din%C3%A2mica%20para%20Engenharia%5D(https%3A%2F%2Fwww.grupogen.com.br%2Fe-book-cinematica-e-dinamica-para-engenharia).%20Grupo%20GEN.%0A%0A%20%20%20%20-%20Robertson%20G%2C%20Caldwell%20G%2C%20Hamill%20J%2C%20Kamen%20G%20(2013)%20%5BResearch%20Methods%20in%20Biomechanics%5D(https%3A%2F%2Fbooks.google.com.br%2Fbooks%3Fid%3DgRn8AAAAQBAJ).%202nd%20Edition.%20Human%20Kinetics.%0A%0A%20%20%20%20-%20Ruina%20A%2C%20Pratap%20R%20(2019)%20%5BIntroduction%20to%20Statics%20and%20Dynamics%5D(https%3A%2F%2Fruina.tam.cornell.edu%2FBook%2Findex.html).%20Oxford%20University%20Press.%0A%0A%20%20%20%20-%20Siciliano%20B%2C%20Sciavicco%20L%2C%20Villani%20L%2C%20Oriolo%20G%20(2009)%20%5BRobotics%20-%20Modelling%2C%20Planning%20and%20Control%5D(https%3A%2F%2Fbooks.google.com.br%2Fbooks%2Fabout%2FRobotics.html%3Fhl%3Dpt-BR%26id%3DjPCAFmE-logC).%20Springer-Verlag%20London.%0A%0A%20%20%20%20-%20Winter%20DA%20(2009)%20%5BBiomechanics%20and%20motor%20control%20of%20human%20movement%5D(https%3A%2F%2Fbooks.google.com.br%2Fbooks%3Fid%3D_bFHL08IWfwC).%204%20ed.%20Hoboken%2C%20USA%3A%20Wiley.%0A%0A%20%20%20%20-%20Wu%20G%2C%20Cavanagh%20PR%20(1995)%20%5BISB%20recommendations%20for%20standardization%20in%20the%20reporting%20of%20kinematic%20data%5D(https%3A%2F%2Fdoi.org%2F10.1016%2F0021-9290(95)00017-C).%20Journal%20of%20Biomechanics%2C%2028(10)%2C%201257%E2%80%931261.%0A%0A%20%20%20%20-%20Zatsiorsky%20VM%20(1997)%20%5BKinematics%20of%20Human%20Motion%5D(https%3A%2F%2Fbooks.google.com.br%2Fbooks%2Fabout%2FKinematics_of_Human_Motion.html%3Fid%3DPql_xXdbrMcC%26redir_esc%3Dy).%20Champaign%2C%20Human%20Kinetics.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
b858b92b3c72eddd170f5baf59bbaf85