%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%22sympy%3E%3D1.13%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%20a%20plane%20(2D)%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%20A%20motion%20capture%20system%20measures%20markers%20in%20the%20coordinate%20system%20of%20the%20laboratory.%20But%20the%20questions%20we%20ask%20are%20about%20body%20segments%3A%20how%20far%20the%20thigh%20has%20rotated%2C%20where%20the%20knee%20joint%20is%2C%20what%20angle%20the%20knee%20makes.%20Answering%20them%20means%20moving%20back%20and%20forth%20between%20the%20laboratory's%20coordinate%20system%20and%20coordinate%20systems%20attached%20to%20the%20segments%2C%20and%20the%20tool%20for%20that%20is%20the%20rigid-body%20transformation%3A%20a%20translation%2C%20a%20rotation%2C%20or%20both.%0A%0A%20%20%20%20This%20notebook%20builds%20that%20tool%20in%20the%20simplest%20setting%2C%20a%20plane%2C%20where%20a%20rotation%20is%20a%20single%20angle.%20It%20derives%20the%20rotation%20matrix%20three%20different%20ways%2C%20shows%20how%20to%20invert%20it%20at%20no%20cost%2C%20builds%20it%20from%20marker%20positions%2C%20uses%20it%20for%20segment%20and%20joint%20angles%2C%20and%20combines%20it%20with%20a%20translation.%20It%20ends%20by%20locating%20a%20joint%20that%20carries%20no%20marker%2C%20which%20is%20what%20the%20whole%20apparatus%20is%20for.%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%20**Exercises**%20come%20with%20worked%20solutions%2C%20folded%20away%20under%20a%20*Solution*%20heading.%20Try%20each%20one%20on%20paper%20or%20in%20a%20new%20cell%20first%2C%20and%20open%20the%20solution%20only%20to%20check%20your%20answer.%0A%0A%20%20%20%20You%20will%20need%20the%20vector%20operations%20from%20%5BScalar%20and%20vector%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fscalar_vector.py)%2C%20the%20idea%20of%20a%20basis%20from%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py)%2C%20and%20matrix%20multiplication%20from%20%5BMatrix%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmatrix.py).%0A%0A%20%20%20%20**Challenge%200.**%20Put%20a%20coin%20on%20a%20sheet%20of%20paper%20and%20draw%20a%20pair%20of%20x%E2%80%93y%20axes%20on%20the%20paper%2C%20and%20another%20pair%20on%20the%20table.%20Write%20down%20the%20coin's%20coordinates%20in%20both.%20Now%20turn%20the%20paper%20by%20about%2045%C2%B0%20on%20the%20table%2C%20carrying%20the%20coin%20with%20it%2C%20and%20write%20down%20both%20sets%20of%20coordinates%20again.%20Which%20set%20changed%3F%20Keep%20your%20notes%20nearby%3B%20the%20checkpoint%20questions%20ask%20you%20to%20come%20back%20to%20them.%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%20Where%20is%20the%20knee%3F%0A%0A%20%20%20%20In%20a%20gait%20laboratory%2C%20two%20markers%20are%20placed%20on%20the%20side%20of%20a%20person's%20thigh%2C%20seen%20in%20the%20sagittal%20plane%3A%20one%20on%20the%20greater%20trochanter%2C%20near%20the%20hip%2C%20and%20one%20lower%20on%20the%20thigh.%20With%20the%20person%20standing%20still%2C%20the%20position%20of%20the%20knee%20joint%20centre%20is%20also%20located%2C%20for%20example%20midway%20between%20markers%20on%20the%20two%20femoral%20epicondyles.%20Those%20knee%20markers%20are%20then%20taken%20off%2C%20because%20the%20one%20on%20the%20inside%20of%20the%20knee%20would%20be%20knocked%20off%20by%20the%20other%20leg.%20In%20metres%2C%20with%20%24X%24%20pointing%20forward%20and%20%24Y%24%20upwards%3A%0A%0A%20%20%20%20%7C%20%7C%20standing%20(calibration)%20%7C%20during%20the%20movement%20%7C%0A%20%20%20%20%7C---%7C---%7C---%7C%0A%20%20%20%20%7C%20marker%20on%20the%20greater%20trochanter%20%7C%20(0.000%2C%200.900)%20%7C%20(0.150%2C%200.800)%20%7C%0A%20%20%20%20%7C%20marker%20on%20the%20lateral%20thigh%20%7C%20(0.020%2C%200.700)%20%7C%20(0.333%2C%200.717)%20%7C%0A%20%20%20%20%7C%20knee%20joint%20centre%20%7C%20(0.010%2C%200.480)%20%7C%20%3F%20%7C%0A%0A%20%20%20%20The%20thigh%20is%20a%20rigid%20body%2C%20so%20the%20knee%20is%20still%20exactly%20where%20it%20was%20*relative%20to%20the%20thigh*.%20But%20the%20thigh%20has%20moved%20and%20turned%2C%20so%20its%20position%20relative%20to%20the%20laboratory%20has%20changed%2C%20and%20there%20is%20no%20marker%20on%20it%20to%20tell%20us%20where.%20**Where%20is%20the%20knee%20during%20the%20movement%3F**%0A%0A%20%20%20%20**Guiding%20questions%200.**%0A%0A%20%20%20%201.%20The%20knee%20is%2042%20cm%20from%20the%20marker%20on%20the%20greater%20trochanter.%20Is%20knowing%20where%20that%20marker%20is%20now%20enough%20to%20locate%20the%20knee%3F%20What%20else%20do%20you%20need%3F%0A%20%20%20%202.%20How%20many%20numbers%20are%20needed%20to%20describe%20where%20the%20thigh%20is%20in%20the%20plane%3F%20Which%20of%20them%20can%20you%20get%20from%20the%20two%20markers%3F%0A%20%20%20%203.%20Make%20a%20rough%20guess%3A%20during%20the%20movement%2C%20is%20the%20knee%20in%20front%20of%20or%20behind%20the%20trochanter%20marker%3F%20Above%20or%20below%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%20Python%20setup%0A%0A%20%20%20%20NumPy%20does%20the%20numerical%20work%20and%20Matplotlib%20draws%20the%20figures.%20SymPy%20appears%20once%2C%20for%20a%20symbolic%20product%20of%20rotation%20matrices.%20The%20print%20options%20show%20four%20decimals%20and%20suppress%20the%20scientific%20notation%20of%20numbers%20that%20are%20zero%20up%20to%20rounding.%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%20matplotlib%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%0A%20%20%20%20np.set_printoptions(precision%3D4%2C%20suppress%3DTrue)%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%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%20Affine%20transformations%0A%0A%20%20%20%20Translation%20and%20rotation%20are%20two%20examples%20of%20%5Baffine%20transformations%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FAffine_transformation).%20Affine%20transformations%20preserve%20straight%20lines%2C%20but%20not%20necessarily%20the%20distances%20between%20points.%20Other%20examples%20are%20scaling%2C%20shear%20and%20reflection.%20The%20figure%20below%20illustrates%20different%20affine%20transformations%20in%20a%20plane.%20On%20top%20of%20each%20one%20is%20a%203%C3%973%20matrix%2C%20its%20transformation%20matrix%2C%20which%20is%20the%20mathematical%20representation%20of%20the%20physical%20transformation.%20We%20will%20build%20exactly%20this%20kind%20of%20matrix%20for%20the%20translation%20and%20rotation%20of%20a%20rigid%20body.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-1%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F2%2F2c%2F2D_affine_transformation_matrix.svg%22%20width%3D360%20alt%3D%22Affine%20transformations%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.%20Examples%20of%20affine%20transformations%20in%20a%20plane%20applied%20to%20a%20square%20(with%20the%20letter%20%3Cb%3EF%3C%2Fb%3E%20in%20it)%20and%20the%20corresponding%20transformation%20matrices%20(%3Ca%20href%3D%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FAffine_transformation%22%3Eimage%20from%20Wikipedia%3C%2Fa%3E).%3C%2Fspan%3E%0A%0A%20%20%20%20Translation%20and%20rotation%20keep%20every%20distance%20unchanged.%20So%20does%20reflection%2C%20but%20a%20reflection%20turns%20a%20right%20hand%20into%20a%20left%20hand%2C%20which%20no%20physical%20body%20can%20do.%20Translations%2C%20rotations%20and%20their%20combinations%20are%20the%20only%20transformations%20a%20rigid%20body%20can%20undergo.%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%20Kinematics%20of%20a%20rigid%20body%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%3B%20the%20corresponding%20changes%20are%20translation%20and%20rotation.%20The%20translation%20and%20rotation%20of%20a%20rigid%20body%20are%20also%20known%20as%20rigid-body%20transformations%2C%20or%20simply%20rigid%20transformations.%0A%0A%20%20%20%20In%20physics%2C%20a%20%5Brigid%20body%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FRigid_body)%20is%20a%20model%2C%20an%20idealization%2C%20for%20a%20body%20whose%20deformation%20is%20neglected%3A%20the%20distance%20between%20every%20pair%20of%20its%20points%20is%20considered%20constant.%20Consequently%2C%20the%20position%20and%20orientation%20of%20a%20rigid%20body%20can%20be%20completely%20described%20by%20a%20coordinate%20system%20attached%20to%20it.%20Two%20(or%20more)%20coordinate%20systems%20can%20then%20represent%20the%20same%20rigid%20body%20at%20two%20(or%20more)%20instants%2C%20or%20two%20(or%20more)%20rigid%20bodies%20in%20space.%0A%0A%20%20%20%20In%20motion%20analysis%2C%20rigid-body%20transformations%20describe%20the%20position%20and%20orientation%20of%20each%20body%20segment%2C%20through%20a%20local%20(anatomical)%20coordinate%20system%20attached%20to%20the%20segment%2C%20in%20relation%20to%20a%20global%20coordinate%20system%20fixed%20in%20the%20laboratory.%20A%20segment%20may%20also%20carry%20a%20technical%20coordinate%20system%2C%20defined%20by%20markers%20that%20are%20not%20on%20anatomical%20landmarks%3B%20the%20positions%20of%20the%20anatomical%20landmarks%20are%20then%20reconstructed%20from%20it%2C%20which%20is%20exactly%20the%20knee%20problem%20above.%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py)%20describes%20these%20coordinate%20systems%20in%20more%20detail.%0A%0A%20%20%20%20We%20will%20study%20rigid-body%20transformations%20as%20transformations%20between%20two%20coordinate%20systems.%20For%20simplicity%2C%20we%20start%20with%20planar%20(two-dimensional)%20transformations%3B%20%5BRigid-body%20transformations%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_3d.py)%20extends%20them%20to%20three%20dimensions%2C%20where%20rotations%20are%20considerably%20more%20complicated.%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%20In%20a%20plane%2C%20two%20coordinates%20and%20one%20angle%20are%20enough%20to%20describe%20the%20pose%20of%20a%20rigid%20body%3A%20it%20has%20three%20degrees%20of%20freedom.%20Let's%20look%20at%20translation%20first%2C%20then%20at%20rotation%2C%20and%20combine%20them%20at%20the%20end.%0A%0A%20%20%20%20A%20pure%20translation%20of%20one%20coordinate%20system%20relative%20to%20another%2C%20and%20the%20representation%20of%20a%20point%20in%20both%2C%20is%20illustrated%20below.%20Remember%20that%20this%20is%20equivalent%20to%20describing%20the%20translation%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%2Ftranslation2D.png%3Fraw%3D1%22%20width%3D310%20alt%3D%22translation%202D%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%20two-dimensional%20space%20represented%20in%20two%20coordinate%20systems%20(Global%20and%20local)%2C%20with%20one%20system%20translated.%3C%2Fspan%3E%0A%0A%20%20%20%20The%20position%20of%20point%20%24%5Cmathbf%7BP%7D%24%2C%20originally%20described%20in%20the%20local%20coordinate%20system%2C%20described%20in%20the%20Global%20coordinate%20system%20in%20vector%20form%20is%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%20where%20%24%5Cmathbf%7BL_G%7D%24%20is%20the%20position%20of%20the%20local%20origin%20in%20the%20Global%20coordinate%20system.%20For%20each%20component%2C%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%5Cmathbf%7BP_X%7D%20%26%3D%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%26%3D%20%5Cmathbf%7BL_Y%7D%20%2B%20%5Cmathbf%7BP%7D_y%0A%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20in%20matrix%20form%2C%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%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%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%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Because%20position%20and%20translation%20can%20be%20treated%20as%20vectors%2C%20the%20inverse%20operation%2C%20describing%20the%20position%20in%20the%20local%20coordinate%20system%20in%20terms%20of%20the%20Global%20one%2C%20is%20simply%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-%5Cmathbf%7BL_G%7D%0A%20%20%20%20%5Cqquad%20%5Ctext%7Bor%7D%20%5Cqquad%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%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%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%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20-%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%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20A%20translation%20of%20the%20origin%20is%20the%20simplest%20case%20of%20a%20%5BGalilean%20transformation%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FGalilean_transformation)%3B%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py)%20uses%20one%20in%20which%20the%20translation%20grows%20with%20time.%0A%0A%20%20%20%20For%20example%2C%20if%20the%20local%20coordinate%20system%20is%20translated%20by%20%24%5Cmathbf%7BL_G%7D%3D%5B2%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%5D%24%20in%20the%20local%20coordinate%20system%20has%20the%20position%20%24%5Cmathbf%7BP_G%7D%3D%5B6%2C%208%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%20LG%20%3D%20np.array(%5B2%2C%203%5D)%20%20%23%20NumPy%201D%20array%20with%202%20elements%0A%20%20%20%20_Pl%20%3D%20np.array(%5B4%2C%205%5D)%0A%20%20%20%20_PG%20%3D%20LG%20%2B%20_Pl%0A%0A%20%20%20%20print(%22PG%20%3D%22%2C%20_PG)%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%20This%20operation%20also%20works%20with%20more%20than%20one%20point%20at%20once%2C%20one%20point%20per%20row%3B%20NumPy%20knows%20how%20to%20combine%20arrays%20of%20different%20shapes%20(%5Bbroadcasting%5D(https%3A%2F%2Fnumpy.org%2Fdoc%2Fstable%2Fuser%2Fbasics.broadcasting.html))%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(LG%2C%20np)%3A%0A%20%20%20%20_Pl%20%3D%20np.array(%5B%5B4%2C%205%5D%2C%20%5B6%2C%207%5D%2C%20%5B8%2C%209%5D%5D)%20%20%23%202D%20array%20with%203%20rows%20and%202%20columns%0A%20%20%20%20_PG%20%3D%20LG%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%23%23%20Rotation%0A%0A%20%20%20%20A%20pure%20rotation%20of%20one%20coordinate%20system%20relative%20to%20another%2C%20and%20the%20representation%20of%20a%20point%20in%20both%2C%20is%20illustrated%20below%20(again%2C%20this%20is%20equivalent%20to%20describing%20the%20rotation%20between%20two%20rigid%20bodies).%20The%20rotation%20is%20about%20an%20axis%20perpendicular%20to%20the%20page%2C%20not%20shown%20in%20the%20figure%3B%20in%20a%20three-dimensional%20coordinate%20system%20it%20would%20be%20the%20%24%5Cmathbf%7BZ%7D%24%20axis.%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%2Frotation2D.png%3Fraw%3D1%22%20width%3D270%20alt%3D%22rotation%202D%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.%20A%20point%20in%20the%20two-dimensional%20space%20represented%20in%20two%20coordinate%20systems%20(Global%20and%20local)%2C%20with%20one%20system%20rotated%20in%20relation%20to%20the%20other%20around%20an%20axis%20orthogonal%20to%20both%20coordinate%20systems.%3C%2Fspan%3E%0A%0A%20%20%20%20We%20want%20to%20express%20the%20position%20of%20point%20%24%5Cmathbf%7BP%7D%24%20in%20the%20Global%20coordinate%20system%20knowing%20only%20its%20coordinates%20in%20the%20local%20coordinate%20system%20and%20the%20angle%20of%20rotation%20between%20the%20two.%20There%20are%20several%20ways%20to%20work%20it%20out%3B%20here%20are%20three.%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%20Using%20trigonometry%0A%0A%20%20%20%20From%20the%20figure%20below%2C%20the%20coordinates%20of%20point%20%24%5Cmathbf%7BP%7D%24%20in%20the%20Global%20coordinate%20system%20can%20be%20found%20from%20the%20sides%20of%20the%20triangles%20marked%20in%20red.%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%2Frotation2Db.png%3Fraw%3D1%22%20width%3D600%20alt%3D%22rotation%202D%2C%20trigonometry%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.%20The%20coordinates%20of%20a%20point%20in%20the%20Global%20coordinate%20system%20in%20terms%20of%20its%20coordinates%20in%20the%20local%20coordinate%20system.%3C%2Fspan%3E%0A%0A%20%20%20%20Then%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%5Cmathbf%7BP_X%7D%20%26%3D%20%5Cmathbf%7BP%7D_x%20%5Ccos%20%5Calpha%20-%20%5Cmathbf%7BP%7D_y%20%5Csin%20%5Calpha%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP_Y%7D%20%26%3D%20%5Cmathbf%7BP%7D_x%20%5Csin%20%5Calpha%20%2B%20%5Cmathbf%7BP%7D_y%20%5Ccos%20%5Calpha%0A%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20In%20matrix%20form%2C%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%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%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%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%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20where%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20is%20the%20rotation%20matrix%20that%20rotates%20the%20coordinates%20from%20the%20local%20to%20the%20Global%20coordinate%20system%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%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Read%20the%20subscripts%20from%20right%20to%20left%3A%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20takes%20coordinates%20in%20%24l%24%20and%20returns%20coordinates%20in%20%24G%24.%20With%20it%2C%20any%20position%20in%20the%20local%20coordinate%20system%20can%20be%20expressed%20in%20the%20Global%20one.%20Let's%20check%20that%20before%20looking%20at%20the%20other%20ways%20of%20obtaining%20the%20matrix.%0A%0A%20%20%20%20Consider%20a%20local%20coordinate%20system%20rotated%20by%20%2445%5E%5Ccirc%24%20in%20relation%20to%20the%20Global%20coordinate%20system%2C%20and%20a%20point%20at%20%24%5Cmathbf%7BP_l%7D%3D%5B1%2C%201%5D%24%20in%20the%20local%20coordinate%20system.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20its%20Global%20coordinates.%20(Hint%3A%20where%20does%20the%20diagonal%20of%20the%20local%20coordinate%20system%20point%3F)%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_alpha%20%3D%20np.pi%20%2F%204%0A%20%20%20%20RGl%20%3D%20np.array(%5B%5Bnp.cos(_alpha)%2C%20-np.sin(_alpha)%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bnp.sin(_alpha)%2C%20%20np.cos(_alpha)%5D%5D)%0A%20%20%20%20_Pl%20%3D%20np.array(%5B%5B1%2C%201%5D%5D).T%20%20%23%20transpose%20the%20array%20for%20correct%20matrix%20multiplication%0A%20%20%20%20_PG%20%3D%20RGl%20%40%20_Pl%20%20%23%20the%20operator%20%40%20is%20used%20for%20matrix%20multiplication%20of%20arrays%0A%0A%20%20%20%20print(%22PG%20%3D%5Cn%22%2C%20_PG)%0A%20%20%20%20return%20(RGl%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%20local%20diagonal%2C%20at%20%2445%5E%5Ccirc%24%20in%20the%20local%20system%2C%20ends%20up%20at%20%2490%5E%5Ccirc%24%20in%20the%20Global%20one%3A%20the%20point%20lies%20on%20the%20Global%20%24%5Cmathbf%7BY%7D%24%20axis%2C%20at%20a%20distance%20%24%5Csqrt%7B2%7D%20%3D%201.4142%24%20from%20the%20origin%2C%20as%20it%20was%20in%20the%20local%20system.%20A%20rotation%20changes%20coordinates%2C%20never%20distances.%0A%0A%20%20%20%20With%20the%20points%20%24%5B1%2C1%5D%24%2C%20%24%5B0%2C1%5D%24%20and%20%24%5B1%2C0%5D%24%20in%20the%20local%20coordinate%20system%2C%20one%20per%20column%2C%20their%20positions%20in%20the%20Global%20coordinate%20system%20are%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RGl%2C%20np)%3A%0A%20%20%20%20_Pl%20%3D%20np.array(%5B%5B1%2C%201%5D%2C%20%5B0%2C%201%5D%2C%20%5B1%2C%200%5D%5D).T%20%20%23%20transpose%3A%20one%20point%20per%20column%0A%20%20%20%20_PG%20%3D%20RGl%20%40%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%20Note%20the%20orientation%20of%20the%20arrays.%20With%20the%20rotation%20matrix%20on%20the%20left%2C%20%24%5Cmathbf%7BR%7D%5C%2C%5Cmathbf%7BP%7D%24%2C%20the%20points%20must%20be%20*columns*%3B%20with%20data%20stored%20one%20point%20per%20row%2C%20as%20marker%20data%20usually%20are%2C%20the%20equivalent%20product%20is%20%60P%20%40%20R.T%60.%0A%0A%20%20%20%20We%20will%20build%20this%20matrix%20many%20more%20times%2C%20so%20let's%20write%20it%20as%20a%20function%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20rotation_2d(alpha)%3A%0A%20%20%20%20%22%22%22Matrix%20that%20rotates%20planar%20coordinates%20by%20the%20angle%20%60alpha%60%20%5Brad%5D%2C%0A%20%20%20%20counterclockwise%3B%20it%20is%20R_Gl%20for%20a%20local%20system%20rotated%20by%20%60alpha%60.%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20return%20np.array(%5B%5Bnp.cos(alpha)%2C%20-np.sin(alpha)%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bnp.sin(alpha)%2C%20%20np.cos(alpha)%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**Exercise%201.**%20A%20local%20coordinate%20system%20is%20rotated%20by%20%2490%5E%5Ccirc%24%20counterclockwise%20in%20relation%20to%20the%20Global%20one.%20Without%20a%20calculator%2C%20write%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20and%20find%20the%20Global%20coordinates%20of%20the%20local%20points%20%24%5B2%2C%200%5D%24%20and%20%24%5B0%2C%203%5D%24.%20Check%20your%20answers%20with%20a%20sketch.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%201%0A%20%20%20%20With%20%24%5Ccos%2090%5E%5Ccirc%20%3D%200%24%20and%20%24%5Csin%2090%5E%5Ccirc%20%3D%201%24%2C%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%7D%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200%20%26%20-1%20%5C%5C%201%20%26%20%5Chphantom%7B-%7D0%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20so%20%24%5B2%2C%200%5D%24%20goes%20to%20%24%5B0%20%5Ccdot%202%20-%201%20%5Ccdot%200%2C%5C%3B%201%20%5Ccdot%202%20%2B%200%20%5Ccdot%200%5D%20%3D%20%5B0%2C%202%5D%24%2C%20and%20%24%5B0%2C%203%5D%24%20goes%20to%20%24%5B-3%2C%200%5D%24.%0A%0A%20%20%20%20In%20the%20sketch%2C%20the%20local%20%24x%24%20axis%20lies%20along%20the%20Global%20%24Y%24%20axis%20and%20the%20local%20%24y%24%20axis%20along%20the%20Global%20%24-X%24%20axis.%20A%20point%202%20along%20local%20%24x%24%20is%20therefore%202%20up%2C%20and%20a%20point%203%20along%20local%20%24y%24%20is%203%20to%20the%20left.%20%60rotation_2d(np.pi%20%2F%202)%20%40%20%5B2%2C%200%5D%60%20confirms%20it.%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%20Using%20direction%20cosines%0A%0A%20%20%20%20Another%20way%20to%20determine%20the%20rotation%20matrix%20uses%20the%20concept%20of%20direction%20cosine.%0A%0A%20%20%20%20%3E%20Direction%20cosines%20are%20the%20cosines%20of%20the%20angles%20between%20any%20two%20vectors.%0A%0A%20%20%20%20With%20two%20coordinate%20systems%2C%20they%20are%20the%20cosines%20of%20the%20angles%20between%20each%20axis%20of%20one%20coordinate%20system%20and%20each%20axis%20of%20the%20other.%20The%20figure%20below%20illustrates%20these%20direction%20angles%2C%20expressing%20the%20local%20coordinate%20system%20in%20terms%20of%20the%20Global%20coordinate%20system.%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-5%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Fdirectioncosine2D.png%3Fraw%3D1%22%20width%3D285%20alt%3D%22direction%20angles%202D%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.%20Definition%20of%20direction%20angles%20in%20two-dimensional%20space.%3C%2Fspan%3E%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%5C%5C%0A%20%20%20%20%5Ccos%5Cmathbf%7BY%7Dx%20%26%20%5Ccos%5Cmathbf%7BY%7Dy%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos(%5Calpha)%20%26%20%5Ccos(90%5E%5Ccirc%2B%5Calpha)%20%5C%5C%0A%20%20%20%20%5Ccos(90%5E%5Ccirc-%5Calpha)%20%26%20%5Ccos(%5Calpha)%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20same%20rotation%20matrix%20as%20before.%0A%0A%20%20%20%20The%20order%20of%20the%20direction%20cosines%20follows%20from%20our%20convention%3A%20the%20first%20row%20is%20for%20the%20%24%5Cmathbf%7BX%7D%24%20coordinate%20and%20the%20second%20row%20for%20the%20%24%5Cmathbf%7BY%7D%24%20coordinate%20(the%20outputs).%20For%20the%20inputs%20we%20follow%20the%20same%20order%2C%20first%20column%20for%20the%20%24%5Cmathbf%7Bx%7D%24%20coordinate%2C%20second%20column%20for%20the%20%24%5Cmathbf%7By%7D%24%20coordinate.%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%20Using%20a%20basis%0A%0A%20%20%20%20Yet%20another%20way%20to%20deduce%20the%20rotation%20matrix%20is%20to%20view%20the%20axes%20of%20the%20rotated%20coordinate%20system%20as%20unit%20vectors%2C%20versors%2C%20of%20a%20%3Ca%20href%3D%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FBasis_(linear_algebra)%22%3Ebasis%3C%2Fa%3E%2C%20as%20illustrated%20in%20the%20figure%20below.%0A%0A%20%20%20%20%3E%20A%20basis%20is%20a%20set%20of%20linearly%20independent%20vectors%20that%20can%20represent%20every%20vector%20in%20a%20given%20vector%20space%2C%20that%20is%2C%20a%20basis%20defines%20a%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%2Fbasis2D2.png%3Fraw%3D1%22%20width%3D285%20alt%3D%22basis%202D%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.%20Definition%20of%20the%20rotation%20matrix%20using%20a%20basis%20in%20two-dimensional%20space.%3C%2Fspan%3E%0A%0A%20%20%20%20The%20versors%20of%20the%20local%20coordinate%20system%2C%20written%20in%20terms%20of%20the%20versors%20of%20the%20Global%20coordinate%20system%2C%20are%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%5Chat%7B%5Cmathbf%7Be%7D%7D_x%20%26%3D%20%5Chphantom%7B-%7D%5Ccos%5Calpha%5C%3A%5Chat%7B%5Cmathbf%7Be%7D%7D_X%20%2B%20%5Csin%5Calpha%5C%3A%5Chat%7B%5Cmathbf%7Be%7D%7D_Y%20%5C%5C%0A%20%20%20%20%5Chat%7B%5Cmathbf%7Be%7D%7D_y%20%26%3D%20-%5Csin%5Calpha%5C%3A%5Chat%7B%5Cmathbf%7Be%7D%7D_X%20%2B%20%5Ccos%5Calpha%5C%3A%5Chat%7B%5Cmathbf%7Be%7D%7D_Y%0A%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20As%20versors%2C%20each%20of%20them%20has%20norm%20one%2C%20which%20indeed%20is%20the%20case.%20Placing%20each%20versor%20as%20a%20column%20of%20a%20matrix%20gives%20the%20rotation%20matrix%20once%20more%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%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20So%20the%20rotation%20matrix%20*is*%20the%20basis%20of%20the%20rotated%20coordinate%20system%3A%20its%20columns%20are%20the%20local%20versors%2C%20written%20in%20Global%20coordinates.%0A%0A%20%20%20%20This%20third%20way%20of%20deriving%20the%20rotation%20matrix%20is%20the%20one%20most%20used%20in%20motion%20analysis%2C%20because%20the%20coordinates%20of%20markers%20in%20the%20Global%20(laboratory)%20coordinate%20system%20are%20what%20cameras%20measure%2C%20and%20the%20versors%20are%20built%20from%20them.%20Before%20doing%20that%2C%20let's%20see%20how%20to%20go%20the%20other%20way%2C%20from%20Global%20to%20local%20coordinates.%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%20Local-to-Global%20and%20Global-to-local%20rotations%0A%0A%20%20%20%20For%20the%20inverse%20operation%2C%20expressing%20the%20position%20of%20point%20%24%5Cmathbf%7BP%7D%24%20in%20the%20local%20coordinate%20system%20in%20terms%20of%20the%20Global%20coordinate%20system%2C%20the%20figure%20below%20shows%20the%20trigonometry.%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%2Frotation2Dc.png%3Fraw%3D1%22%20width%3D600%20alt%3D%22rotation%202D%2C%20inverse%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.%20The%20coordinates%20of%20a%20point%20in%20the%20local%20coordinate%20system%20in%20terms%20of%20its%20coordinates%20in%20the%20Global%20coordinate%20system.%3C%2Fspan%3E%0A%0A%20%20%20%20Then%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%5Cmathbf%7BP%7D_x%20%26%3D%20%5Chphantom%7B-%7D%5Cmathbf%7BP_X%7D%20%5Ccos%20%5Calpha%20%2B%20%5Cmathbf%7BP_Y%7D%20%5Csin%20%5Calpha%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP%7D_y%20%26%3D%20-%5Cmathbf%7BP_X%7D%20%5Csin%20%5Calpha%20%2B%20%5Cmathbf%7BP_Y%7D%20%5Ccos%20%5Calpha%0A%20%20%20%20%5Cend%7Baligned%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%7D_x%20%5C%5C%0A%20%20%20%20%5Cmathbf%7BP%7D_y%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Chphantom%7B-%7D%5Ccos%5Calpha%20%26%20%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20-%5Csin%5Calpha%20%26%20%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%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%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cqquad%20%5Ctext%7Bor%7D%20%5Cqquad%0A%20%20%20%20%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BR_%7BlG%7D%7D%5Cmathbf%7BP_G%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20where%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%20is%20the%20rotation%20matrix%20that%20rotates%20the%20coordinates%20from%20the%20Global%20to%20the%20local%20coordinate%20system%20(note%20the%20inverse%20order%20of%20the%20subscripts)%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR_%7BlG%7D%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Chphantom%7B-%7D%5Ccos%5Calpha%20%26%20%5Csin%5Calpha%20%5C%5C%0A%20%20%20%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%20With%20direction%20cosines%2C%20the%20angles%20between%20the%20axes%20have%20not%20changed%2C%20so%20the%20cosines%20are%20the%20same%3B%20only%20their%20order%20changes.%20Now%20%24%5Cmathbf%7Bx%2C%20y%7D%24%20are%20the%20rows%20(outputs)%20and%20%24%5Cmathbf%7BX%2C%20Y%7D%24%20are%20the%20columns%20(inputs)%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR_%7BlG%7D%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Cmathbf%7BX%7Dx%20%26%20%5Ccos%5Cmathbf%7BY%7Dx%20%5C%5C%0A%20%20%20%20%5Ccos%5Cmathbf%7BX%7Dy%20%26%20%5Ccos%5Cmathbf%7BY%7Dy%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos(%5Calpha)%20%26%20%5Ccos(90%5E%5Ccirc-%5Calpha)%20%5C%5C%0A%20%20%20%20%5Ccos(90%5E%5Ccirc%2B%5Calpha)%20%26%20%5Ccos(%5Calpha)%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Chphantom%7B-%7D%5Ccos%5Calpha%20%26%20%5Csin%5Calpha%20%5C%5C%0A%20%20%20%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%20And%20writing%20the%20versors%20of%20the%20Global%20axes%20as%20a%20basis%20in%20terms%20of%20the%20local%20coordinate%20system%20would%20produce%20this%20matrix%20too.%0A%0A%20%20%20%20The%20two%20matrices%20are%20very%20similar%2C%20and%20that%20is%20no%20coincidence.%20Each%20performs%20the%20inverse%20operation%20of%20the%20other%3A%20each%20matrix%20is%20the%20inverse%20of%20the%20other.%20Equivalently%2C%20instead%20of%20rotating%20the%20local%20coordinate%20system%20by%20%24%5Calpha%24%20relative%20to%20the%20Global%20one%2C%20we%20may%20rotate%20the%20Global%20coordinate%20system%20by%20%24-%5Calpha%24%20relative%20to%20the%20local%20one%3B%20remember%20that%20%24%5Ccos(-%5Calpha)%3D%5Ccos(%5Calpha)%24%20and%20%24%5Csin(-%5Calpha)%3D-%5Csin(%5Calpha)%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%20The%20orthogonality%20of%20the%20rotation%20matrix%0A%0A%20%20%20%20(See%20%5BMatrix%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmatrix.py)%20for%20a%20review%20of%20matrices%20and%20their%20main%20properties.)%0A%0A%20%20%20%20A%20very%20useful%20property%20of%20the%20rotation%20matrix%20is%20that%20its%20inverse%20is%20its%20transpose%2C%20because%20its%20columns%20(and%20its%20rows)%20are%20mutually%20orthogonal%20and%20have%20norm%20one.%20We%20can%20show%20it%20with%20the%20matrices%20we%20deduced%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%5Cmathbf%7BR%7D%5C%3A%5Cmathbf%7BR%5ET%7D%20%26%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Chphantom%7B-%7D%5Ccos%5Calpha%20%26%20%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20-%5Csin%5Calpha%20%26%20%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5E2%5Calpha%2B%5Csin%5E2%5Calpha%20%26%20%5Ccos%5Calpha%20%5Csin%5Calpha-%5Csin%5Calpha%20%5Ccos%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%5Ccos%5Calpha-%5Ccos%5Calpha%20%5Csin%5Calpha%20%26%20%5Csin%5E2%5Calpha%2B%5Ccos%5E2%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%5C%5C%0A%20%20%20%20%26%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%201%20%26%200%20%5C%5C%0A%20%20%20%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%20%5Cmathbf%7BI%7D%0A%20%20%20%20%5Cquad%20%5CLongrightarrow%20%5Cquad%0A%20%20%20%20%5Cmathbf%7BR%5E%7B-1%7D%7D%20%3D%20%5Cmathbf%7BR%5ET%7D%0A%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20If%20we%20have%20a%20rotation%20matrix%2C%20we%20have%20its%20inverse%20for%20free.%20In%20NumPy%2C%20the%20transpose%20is%20an%20attribute%20of%20the%20array%20and%20the%20inverse%20is%20a%20function%20of%20%60numpy.linalg%60%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RGl%2C%20np)%3A%0A%20%20%20%20print(%22Orthogonal%20matrix%20(RGl)%3A%5Cn%22%2C%20RGl)%0A%20%20%20%20print(%22Transpose%20(RGl.T)%3A%5Cn%22%2C%20RGl.T)%0A%20%20%20%20print(%22Inverse%20(np.linalg.inv(RGl))%3A%5Cn%22%2C%20np.linalg.inv(RGl))%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%20inverse%2C%20or%20the%20transpose%2C%20the%20coordinates%20in%20the%20local%20coordinate%20system%20follow%20from%20the%20coordinates%20in%20the%20Global%20coordinate%20system%20and%20the%20rotation%20matrix%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%20%26%20%5Cimplies%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%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%20%5C%5C%0A%20%20%20%20%26%20%5Cimplies%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BI%7D%5C%3A%5Cmathbf%7BP_l%7D%20%5C%5C%0A%20%20%20%20%26%20%5Cimplies%20%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5ET%7D%5Cmathbf%7BP_G%7D%0A%20%20%20%20%5Cquad%20%5Ctext%7Bor%7D%20%5Cquad%20%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BR_%7BlG%7D%7D%5Cmathbf%7BP_G%7D%0A%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20where%20we%20called%20the%20inverse%20of%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%2C%20%24%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%24%2C%20by%20the%20name%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%20(note%20the%20order%20of%20the%20subscripts).%20In%20NumPy%2C%20going%20there%20and%20back%20again%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RGl%2C%20np)%3A%0A%20%20%20%20print(%22Rotation%20matrix%20(RGl)%3A%5Cn%22%2C%20RGl)%0A%0A%20%20%20%20_Pl%20%3D%20np.array(%5B%5B1%2C%201%5D%5D).T%20%20%23%20transpose%20the%20array%20for%20correct%20matrix%20multiplication%0A%20%20%20%20print(%22Position%20in%20the%20local%20coordinate%20system%20(Pl)%3A%5Cn%22%2C%20_Pl)%0A%0A%20%20%20%20_PG%20%3D%20RGl%20%40%20_Pl%0A%20%20%20%20print(%22Position%20in%20the%20Global%20coordinate%20system%20(PG%20%3D%20RGl%20Pl)%3A%5Cn%22%2C%20_PG)%0A%0A%20%20%20%20_Pl_back%20%3D%20RGl.T%20%40%20_PG%0A%20%20%20%20print(%22Position%20in%20the%20local%20coordinate%20system%20using%20the%20inverse%20of%20RGl%20(Pl%20%3D%20RlG%20PG)%3A%5Cn%22%2C%20_Pl_back)%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%20Rotation%20of%20a%20vector%0A%0A%20%20%20%20The%20rotation%20matrix%20has%20another%20use%3A%20to%20rotate%20a%20vector%20by%20a%20given%20angle%20around%20an%20axis%20of%20the%20coordinate%20system%2C%20as%20in%20the%20figure%20below.%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%2Frotation2Dvector.png%3Fraw%3D1%22%20width%3D205%20alt%3D%22rotation%20of%20a%20vector%20in%202D%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.%20Rotation%20of%20a%20position%20vector%20%24%5Cmathbf%7BP%7D%24%20by%20an%20angle%20%24%5Calpha%24%20in%20two-dimensional%20space.%3C%2Fspan%3E%0A%0A%20%20%20%20This%20time%20the%20coordinate%20system%20stays%20where%20it%20is%20and%20the%20vector%20turns.%20We%20will%20not%20prove%20it%2C%20but%20the%20same%20rotation%20matrix%20does%20the%20job%3A%20the%20coordinates%20of%20the%20position%20vector%20%24%5Cmathbf%7BP'%7D%24%2C%20rotated%20by%20an%20angle%20%24%5Calpha%24%2C%20are%20the%20rotation%20matrix%20for%20the%20angle%20%24%5Calpha%24%20times%20the%20coordinates%20of%20%24%5Cmathbf%7BP%7D%24%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP'%7D%20%3D%20%5Cmathbf%7BR%7D_%5Calpha%5Cmathbf%7BP%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20For%20example%2C%20for%20%24%5Cmathbf%7BP%7D%3D%5B2%2C1%5D%24%20and%20%24%5Calpha%3D30%5E%5Ccirc%24%2C%20the%20coordinates%20of%20%24%5Cmathbf%7BP'%7D%24%20are%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_alpha%20%3D%20np.pi%20%2F%206%0A%20%20%20%20_R%20%3D%20np.array(%5B%5Bnp.cos(_alpha)%2C%20-np.sin(_alpha)%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bnp.sin(_alpha)%2C%20%20np.cos(_alpha)%5D%5D)%0A%20%20%20%20_P%20%3D%20np.array(%5B%5B2%2C%201%5D%5D).T%0A%20%20%20%20_P_rotated%20%3D%20_R%20%40%20_P%0A%0A%20%20%20%20print(%22P'%20%3D%5Cn%22%2C%20_P_rotated)%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%20So%20the%20same%20matrix%20has%20two%20readings.%20Applied%20to%20the%20coordinates%20of%20a%20point%20that%20stays%20put%2C%20it%20converts%20them%20from%20a%20rotated%20coordinate%20system%20to%20the%20original%20one.%20Applied%20to%20a%20vector%20in%20a%20coordinate%20system%20that%20stays%20put%2C%20it%20turns%20the%20vector.%20The%20two%20are%20easy%20to%20mix%20up%2C%20and%20the%20mix-up%20costs%20a%20sign.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20now%20keep%20the%20vector%20%24%5Cmathbf%7BP%7D%3D%5B2%2C1%5D%24%20where%20it%20is%2C%20and%20turn%20the%20*coordinate%20system*%20by%20%2430%5E%5Ccirc%24%20counterclockwise%20instead.%20What%20are%20the%20coordinates%20of%20the%20same%2C%20unmoved%2C%20point%20in%20the%20turned%20coordinate%20system%3F%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_R30%20%3D%20rotation_2d(np.pi%20%2F%206)%0A%20%20%20%20_P%20%3D%20np.array(%5B2%2C%201%5D)%0A%0A%20%20%20%20print(%22Vector%20turned%20by%20%2B30%20degrees%2C%20coordinate%20system%20fixed%3A%20%20R%20P%20%20%20%3D%22%2C%20_R30%20%40%20_P)%0A%20%20%20%20print(%22Coordinate%20system%20turned%20by%20%2B30%20degrees%2C%20point%20fixed%3A%20%20R.T%20P%20%3D%22%2C%20_R30.T%20%40%20_P)%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%20Turning%20the%20axes%20counterclockwise%20makes%20a%20fixed%20point%20appear%20to%20turn%20*clockwise*%20relative%20to%20them%2C%20by%20the%20same%20angle.%20So%20its%20new%20coordinates%20come%20from%20%24%5Cmathbf%7BR%7D_%7B-%5Calpha%7D%20%3D%20%5Cmathbf%7BR%7D_%7B%5Calpha%7D%5ET%24%2C%20not%20from%20%24%5Cmathbf%7BR%7D_%7B%5Calpha%7D%24%3A%20%24%5B2.2321%2C%20-0.134%5D%24%20instead%20of%20%24%5B1.2321%2C%201.866%5D%24.%20Whenever%20you%20take%20a%20rotation%20matrix%20from%20a%20book%20or%20a%20library%2C%20find%20out%20which%20of%20the%20two%20readings%20it%20was%20written%20for.%0A%0A%20%20%20%20**In%20summary%2C%20some%20of%20the%20properties%20of%20the%20rotation%20matrix%20are%3A**%0A%0A%20%20%20%201.%20Its%20columns%20form%20a%20basis%20of%20independent%20unit%20vectors%20(versors)%2C%20and%20so%20do%20its%20rows%2C%20since%20the%20transpose%20of%20a%20rotation%20matrix%20is%20another%20rotation%20matrix.%0A%20%20%20%202.%20It%20is%20orthogonal%3A%20its%20rows%20are%20mutually%20orthogonal%2C%20and%20so%20are%20its%20columns%20(property%201%20rewritten).%20Because%20each%20row%20and%20column%20also%20has%20norm%20one%2C%20the%20matrix%20is%20sometimes%20called%20orthonormal.%0A%20%20%20%203.%20Its%20determinant%20is%20%24%2B1%24.%20For%20the%20matrix%20we%20deduced%2C%20%24%5Ccos%5Calpha%20%5Ccos%5Calpha%20-%20%5Csin%5Calpha(-%5Csin%5Calpha)%3D1%24.%20A%20matrix%20with%20orthonormal%20columns%20and%20determinant%20%24-1%24%20is%20not%20a%20rotation%3A%20it%20includes%20a%20reflection%2C%20and%20it%20appears%20when%20one%20of%20the%20two%20coordinate%20systems%20is%20left-handed%2C%20which%20you%20should%20rarely%20if%20ever%20use.%0A%20%20%20%204.%20Its%20inverse%20is%20its%20transpose.%0A%0A%20%20%20%20**On%20the%20different%20meanings%20of%20the%20rotation%20matrix%3A**%0A%0A%20%20%20%20-%20It%20represents%20the%20transformation%20between%20the%20coordinates%20of%20a%20point%20expressed%20in%20two%20different%20coordinate%20systems.%0A%20%20%20%20-%20It%20describes%20the%20rotation%20between%20two%20coordinate%20systems.%20Its%20columns%20are%20the%20direction%20cosines%20(versors)%20of%20the%20axes%20of%20the%20rotated%20coordinate%20system%20in%20relation%20to%20the%20other%20coordinate%20system%2C%20and%20its%20rows%20are%20the%20direction%20cosines%20(versors)%20for%20the%20inverse%20rotation.%0A%20%20%20%20-%20It%20is%20an%20operator%20that%20rotates%20a%20vector%20within%20one%20coordinate%20system.%0A%20%20%20%20-%20It%20represents%20a%20rotation%20numerically%2C%20without%20appealing%20to%20any%20particular%20specification%20of%20angles.%0A%0A%20%20%20%20**Which%20matrix%20to%20use%2C%20from%20local%20to%20Global%20or%20from%20Global%20to%20local%3F**%0A%0A%20%20%20%20-%20In%20movement%20analysis%20there%20is%20a%20fixed%20Global%20(laboratory)%20coordinate%20system%20and%20a%20local%20(moving%2C%20for%20example%20anatomical)%20coordinate%20system%20attached%20to%20each%20body%20segment.%20The%20movement%20of%20the%20segment%20is%20measured%20in%20the%20Global%20coordinate%20system%2C%20by%20cameras%20for%20example%2C%20and%20to%20reconstruct%20the%20coordinates%20of%20the%20markers%20in%20the%20anatomical%20coordinate%20system%20we%20need%20the%20transformation%20from%20Global%20to%20local.%0A%20%20%20%20-%20Of%20course%2C%20if%20you%20have%20one%20of%20the%20matrices%2C%20the%20other%20is%20just%20its%20transpose%3B%20you%20only%20have%20to%20be%20careful%20to%20use%20the%20right%20one.%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**Exercise%202.**%20Which%20of%20these%20matrices%20are%20rotation%20matrices%3F%20For%20each%20one%20that%20is%2C%20find%20the%20angle%20of%20rotation.%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BM%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200.6%20%26%20-0.8%20%5C%5C%200.8%20%26%20%5Chphantom%7B-%7D0.6%20%5Cend%7Bbmatrix%7D%2C%20%5Cqquad%0A%20%20%20%20%5Cmathbf%7BN%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200.6%20%26%20%5Chphantom%7B-%7D0.8%20%5C%5C%200.8%20%26%20-0.6%20%5Cend%7Bbmatrix%7D%2C%20%5Cqquad%0A%20%20%20%20%5Cmathbf%7BK%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200.8%20%26%20-0.6%20%5C%5C%200.5%20%26%20%5Chphantom%7B-%7D0.8%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Use%20the%20properties%20listed%20above.%20The%20solution%20checks%20them%20with%20NumPy.%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_matrices%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22M%22%3A%20np.array(%5B%5B0.6%2C%20-0.8%5D%2C%20%5B0.8%2C%200.6%5D%5D)%2C%0A%20%20%20%20%20%20%20%20%22N%22%3A%20np.array(%5B%5B0.6%2C%200.8%5D%2C%20%5B0.8%2C%20-0.6%5D%5D)%2C%0A%20%20%20%20%20%20%20%20%22K%22%3A%20np.array(%5B%5B0.8%2C%20-0.6%5D%2C%20%5B0.5%2C%200.8%5D%5D)%2C%0A%20%20%20%20%7D%0A%20%20%20%20_rows%2C%20_angles%20%3D%20%5B%5D%2C%20%7B%7D%0A%20%20%20%20for%20_name%2C%20_M%20in%20_matrices.items()%3A%0A%20%20%20%20%20%20%20%20_norms%20%3D%20np.linalg.norm(_M%2C%20axis%3D0)%0A%20%20%20%20%20%20%20%20_det%20%3D%20np.linalg.det(_M)%0A%20%20%20%20%20%20%20%20_orthonormal%20%3D%20np.allclose(_M.T%20%40%20_M%2C%20np.eye(2))%0A%20%20%20%20%20%20%20%20_angles%5B_name%5D%20%3D%20np.degrees(np.arctan2(_M%5B1%2C%200%5D%2C%20_M%5B0%2C%200%5D))%0A%20%20%20%20%20%20%20%20if%20_orthonormal%20and%20np.isclose(_det%2C%201)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_verdict%20%3D%20f%22rotation%20by%20%7B_angles%5B_name%5D%3A.2f%7D%C2%B0%22%0A%20%20%20%20%20%20%20%20elif%20_orthonormal%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_verdict%20%3D%20%22orthonormal%2C%20but%20a%20reflection%22%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_verdict%20%3D%20%22not%20orthonormal%22%0A%20%20%20%20%20%20%20%20_rows.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%7C%20%7B_name%7D%20%7C%20%7B_norms%5B0%5D%3A.3f%7D%2C%20%7B_norms%5B1%5D%3A.3f%7D%20%7C%20%7Bround(_M%5B%3A%2C%200%5D%20%40%20_M%5B%3A%2C%201%5D%2C%202)%20%2B%200.0%3A.2f%7D%20%7C%20%7B_det%3A.2f%7D%20%7C%20%7B_verdict%7D%20%7C%22%0A%20%20%20%20%20%20%20%20)%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%202%22%3A%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20matrix%20%7C%20norms%20of%20the%20columns%20%7C%20dot%20product%20of%20the%20columns%20%7C%20determinant%20%7C%20verdict%20%7C%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C---%7C---%7C---%7C---%7C---%7C%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22%5Cn%22.join(_rows)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20f%22Only%20%24%5C%5Cmathbf%7B%7BM%7D%7D%24%20passes%20every%20test%3A%20it%20is%20a%20rotation%20by%20%7B_angles%5B'M'%5D%3A.2f%7D%C2%B0%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22the%20angle%20whose%20cosine%20is%200.6%20and%20whose%20sine%20is%200.8.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20r%22%24%5Cmathbf%7BN%7D%24%20has%20orthonormal%20columns%2C%20but%20its%20determinant%20is%20%24-1%24%3A%20it%20reflects%20the%20plane%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22about%20a%20line%2C%20which%20no%20rigid%20body%20can%20do.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20f%22%24%5C%5Cmathbf%7B%7BK%7D%7D%24%20fails%20at%20once%2C%20because%20its%20first%20column%20is%20not%20a%20versor.%20Yet%20%60arctan2%60%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22returns%20%7B_angles%5B'K'%5D%3A.2f%7D%C2%B0%20for%20%24%5C%5Cmathbf%7B%7BK%7D%7D%24%20and%20%7B_angles%5B'N'%5D%3A.2f%7D%C2%B0%20for%20%24%5C%5Cmathbf%7B%7BN%7D%7D%24%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22without%20complaint.%20A%20formula%20for%20the%20angle%20always%20gives%20a%20number%2C%20so%20check%20that%20the%20matrix%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22is%20a%20rotation%20before%20you%20trust%20it.%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%23%20Calculation%20of%20the%20rotation%20matrix%20using%20a%20basis%0A%0A%20%20%20%20A%20typical%20scenario%20in%20motion%20analysis%20is%20to%20calculate%20the%20rotation%20matrix%20from%20the%20positions%20of%20markers%20placed%20on%20the%20moving%20rigid%20body.%20With%20the%20markers'%20positions%20we%20create%20a%20local%20basis%2C%20which%20by%20definition%20is%20the%20rotation%20matrix%20of%20the%20rigid%20body%20with%20respect%20to%20the%20Global%20(laboratory)%20coordinate%20system.%20To%20define%20a%20coordinate%20system%20from%20the%20basis%2C%20we%20also%20need%20an%20origin.%0A%0A%20%20%20%20Let's%20calculate%20a%20basis%20from%20the%20markers'%20positions.%20Consider%20markers%20at%20%24m_1%3D%5B1%2C1%5D%24%2C%20%24m_2%3D%5B1%2C2%5D%24%20and%20%24m_3%3D%5B-1%2C1%5D%24%2C%20measured%20in%20the%20Global%20coordinate%20system%2C%20as%20illustrated%20in%20the%20figure%20below%3A%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-9%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2Ftransrot2Db.png%3Fraw%3D1%22%20width%3D700%20alt%3D%22translation%20and%20rotation%202D%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.%20Three%20points%20in%20two-dimensional%20space%2C%20two%20possible%20vectors%20given%20these%20points%2C%20and%20the%20corresponding%20basis.%3C%2Fspan%3E%0A%0A%20%20%20%20A%20possible%20local%20coordinate%20system%20with%20origin%20at%20%24m_1%24%20is%20also%20shown%20in%20the%20figure.%20The%20three%20markers%20were%20chosen%20on%20purpose%20so%20that%20the%20two%20vectors%20between%20them%20are%20orthogonal.%20The%20translation%20vector%20between%20the%20two%20coordinate%20systems%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BL_%7BGl%7D%7D%20%3D%20m_1%20-%20%5B0%2C0%5D%20%3D%20%5B1%2C1%5D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20the%20vectors%20along%20the%20axes%20of%20the%20local%20coordinate%20system%20are%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Coverrightarrow%7B%5Cmathbf%7Bx%7D%7D%20%3D%20m_2%20-%20m_1%20%3D%20%5B1%2C2%5D%20-%20%5B1%2C1%5D%20%3D%20%5B0%2C1%5D%2C%0A%20%20%20%20%5Cqquad%0A%20%20%20%20%5Coverrightarrow%7B%5Cmathbf%7By%7D%7D%20%3D%20m_3%20-%20m_1%20%3D%20%5B-1%2C1%5D%20-%20%5B1%2C1%5D%20%3D%20%5B-2%2C0%5D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20These%20two%20vectors%20do%20not%20form%20an%20orthonormal%20basis%20yet%2C%20because%20they%20are%20not%20both%20unit%20vectors%20(%24%5Coverrightarrow%7B%5Cmathbf%7By%7D%7D%24%20is%20not).%20Let's%20normalize%20them%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Chat%7B%5Cmathbf%7Be%7D%7D_x%20%3D%20%5Cfrac%7B%5Coverrightarrow%7B%5Cmathbf%7Bx%7D%7D%7D%7B%7C%7C%5Coverrightarrow%7B%5Cmathbf%7Bx%7D%7D%7C%7C%7D%20%3D%20%5Cfrac%7B%5B0%2C1%5D%7D%7B%5Csqrt%7B0%5E2%2B1%5E2%7D%7D%20%3D%20%5B0%2C1%5D%2C%0A%20%20%20%20%5Cqquad%0A%20%20%20%20%5Chat%7B%5Cmathbf%7Be%7D%7D_y%20%3D%20%5Cfrac%7B%5Coverrightarrow%7B%5Cmathbf%7By%7D%7D%7D%7B%7C%7C%5Coverrightarrow%7B%5Cmathbf%7By%7D%7D%7C%7C%7D%20%3D%20%5Cfrac%7B%5B-2%2C0%5D%7D%7B%5Csqrt%7B2%5E2%2B0%5E2%7D%7D%20%3D%20%5B-1%2C0%5D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Beware%20that%20these%20versors%20are%20not%20drawn%20exactly%20as%20in%20the%20right%20panel%20of%20the%20figure%3A%20plotted%20from%20their%20coordinates%2C%20they%20would%20start%20at%20the%20origin%20of%20the%20Global%20coordinate%20system%2C%20not%20at%20%24%5B1%2C1%5D%24.%0A%0A%20%20%20%20Because%20the%20markers%20were%20carefully%20chosen%2C%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_x%24%20and%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_y%24%20are%20orthogonal.%20We%20could%20have%20done%20this%20calculation%20in%20NumPy%2C%20as%20we%20will%20have%20to%20with%20real%20data%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.0%2C%201.0%5D)%20%20%23%20marker%201%0A%20%20%20%20m2%20%3D%20np.array(%5B1.0%2C%202.0%5D)%20%20%23%20marker%202%0A%20%20%20%20m3%20%3D%20np.array(%5B-1.0%2C%201.0%5D)%20%20%23%20marker%203%0A%0A%20%20%20%20x_axis%20%3D%20m2%20-%20m1%20%20%23%20vector%20x%0A%20%20%20%20y_axis%20%3D%20m3%20-%20m1%20%20%23%20vector%20y%0A%0A%20%20%20%20ex%20%3D%20x_axis%20%2F%20np.linalg.norm(x_axis)%20%20%23%20versor%20x%0A%20%20%20%20ey%20%3D%20y_axis%20%2F%20np.linalg.norm(y_axis)%20%20%23%20versor%20y%0A%0A%20%20%20%20print(%22x%20%3D%22%2C%20x_axis%2C%20%22%2C%20y%20%3D%22%2C%20y_axis%2C%20%22%5Cnex%20%3D%22%2C%20ex%2C%20%22%2C%20ey%20%3D%22%2C%20ey)%0A%20%20%20%20return%20ex%2C%20ey%2C%20m1%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%24%5Chat%7B%5Cmathbf%7Be%7D%7D_x%24%20and%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_y%24%20are%20unit%20vectors%20and%20they%20are%20orthogonal%2C%20so%20they%20form%20a%20basis%2C%20and%20the%20rotation%20matrix%20is%20just%20that%20basis%2C%20with%20the%20versors%20as%20its%20columns%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%200%20%26%20-1%20%5C%5C%0A%20%20%20%201%20%26%20%5Chphantom%7B-%7D0%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20This%20makes%20sense%3A%20the%20figure%20shows%20the%20local%20coordinate%20system%20rotated%20by%20%2490%5E%5Ccirc%24%20in%20relation%20to%20the%20Global%20one%2C%20and%20the%20general%20form%20of%20the%20rotation%20matrix%20gives%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos90%5E%5Ccirc%20%26%20-%5Csin90%5E%5Ccirc%20%5C%5C%0A%20%20%20%20%5Csin90%5E%5Ccirc%20%26%20%5Chphantom%7B-%7D%5Ccos90%5E%5Ccirc%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%200%20%26%20-1%20%5C%5C%0A%20%20%20%201%20%26%20%5Chphantom%7B-%7D0%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20So%20the%20position%20of%20any%20point%20in%20the%20local%20coordinate%20system%20can%20be%20expressed%20in%20the%20Global%20coordinate%20system%20by%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BL_%7BGl%7D%7D%20%2B%20%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%0A%20%20%20%20%3D%20%5Cbegin%7Bbmatrix%7D%201%20%5C%5C%201%20%5Cend%7Bbmatrix%7D%20%2B%20%5Cbegin%7Bbmatrix%7D%200%20%26%20-1%20%5C%5C%201%20%26%20%5Chphantom%7B-%7D0%20%5Cend%7Bbmatrix%7D%20%5Cmathbf%7BP_l%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20(the%20combination%20of%20a%20translation%20and%20a%20rotation%20is%20discussed%20in%20detail%20below).%20For%20example%2C%20the%20point%20%24%5Cmathbf%7BP_l%7D%3D%5B1%2C1%5D%24%20has%20the%20following%20position%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_(ex%2C%20ey%2C%20m1%2C%20np)%3A%0A%20%20%20%20LGl%20%3D%20m1.reshape(2%2C%201)%20%20%23%20translation%20vector%2C%20as%20a%20column%0A%20%20%20%20print(%22Translation%20vector%3A%5Cn%22%2C%20LGl)%0A%0A%20%20%20%20R_basis%20%3D%20np.column_stack((ex%2C%20ey))%20%20%23%20the%20versors%20are%20the%20columns%20of%20RGl%0A%20%20%20%20print(%22Rotation%20matrix%3A%5Cn%22%2C%20R_basis)%0A%0A%20%20%20%20_Pl%20%3D%20np.array(%5B%5B1%2C%201%5D%5D).T%0A%20%20%20%20print(%22Position%20in%20the%20local%20coordinate%20system%3A%5Cn%22%2C%20_Pl)%0A%0A%20%20%20%20_PG%20%3D%20LGl%20%2B%20R_basis%20%40%20_Pl%0A%20%20%20%20print(%22Position%20in%20the%20Global%20coordinate%20system%2C%20PG%20%3D%20LGl%20%2B%20RGl%20Pl%3A%5Cn%22%2C%20_PG)%0A%20%20%20%20return%20LGl%2C%20R_basis%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%20real%20markers%2C%20%24m_3%20-%20m_1%24%20would%20never%20be%20exactly%20perpendicular%20to%20%24m_2%20-%20m_1%24.%20In%20a%20plane%20we%20do%20not%20even%20need%20the%20third%20marker%3A%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_y%24%20is%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_x%24%20turned%20by%20%2490%5E%5Ccirc%24%2C%20%24%5B-e_%7Bx%2CY%7D%2C%5C%3B%20e_%7Bx%2CX%7D%5D%24%2C%20as%20the%20next%20sections%20do.%20(In%20three%20dimensions%2C%20the%20cross%20product%20plays%20this%20role%3B%20see%20%5BDetermination%20of%20a%20coordinate%20system%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fcoordinate_system.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%23%20Determination%20of%20the%20unknown%20angle%20of%20rotation%0A%0A%20%20%20%20If%20we%20did%20not%20know%20the%20angle%20of%20rotation%20between%20the%20two%20coordinate%20systems%2C%20which%20is%20the%20usual%20situation%20in%20motion%20analysis%2C%20we%20would%20equate%20one%20of%20the%20terms%20of%20the%20rotation%20matrix%20in%20its%20algebraic%20form%20to%20its%20numerical%20value%20in%20the%20matrix%20we%20calculated%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20so%20the%20angle%20%24%5Calpha%24%20can%20be%20found%20by%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Calpha%20%3D%20%5Carctan%5Cleft(%5Cfrac%7BR%5B1%2C0%5D%7D%7BR%5B0%2C0%5D%7D%5Cright)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20For%20instance%2C%20the%20first%20term%20of%20the%20rotation%20matrix%20above%2C%20%24%5Ccos%5Calpha%20%3D%200%24%2C%20implies%20that%20%24%5Calpha%24%20is%20%2490%5E%5Ccirc%24%20or%20%24270%5E%5Ccirc%24%3B%20combined%20with%20another%20term%2C%20%24%5Csin%5Calpha%20%3D%201%24%2C%20it%20implies%20that%20%24%5Calpha%3D90%5E%5Ccirc%24.%20We%20can%20solve%20this%20in%20one%20step%20with%20the%20tangent%20%24(%5Csin%5Calpha%2F%5Ccos%5Calpha)%24%20of%20two%20terms%20of%20the%20rotation%20matrix%2C%20using%20the%20function%20%60arctan2(y%2C%20x)%60%2C%20which%20keeps%20the%20signs%20of%20both%20terms%20and%20so%20finds%20the%20right%20quadrant%20(see%20%5BAngular%20kinematics%20in%20a%20plane%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_angular_2d.py))%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R_basis%2C%20np)%3A%0A%20%20%20%20_ang%20%3D%20np.arctan2(R_basis%5B1%2C%200%5D%2C%20R_basis%5B0%2C%200%5D)%20*%20180%20%2F%20np.pi%0A%0A%20%20%20%20print(%22The%20angle%20is%3A%22%2C%20_ang)%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%20This%20procedure%20would%20be%20repeated%20for%20each%20segment%20and%20for%20each%20instant%20of%20the%20movement%20to%20find%20the%20rotation%20of%20each%20segment.%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%20Joint%20angle%20as%20a%20sequence%20of%20rotations%20of%20adjacent%20segments%0A%0A%20%20%20%20In%20%5BAngular%20kinematics%20in%20a%20plane%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_angular_2d.py)%2C%20we%20calculated%20segment%20and%20joint%20angles%20with%20simple%20trigonometric%20relations.%20We%20can%20also%20calculate%20them%20with%20rotation%20matrices.%0A%0A%20%20%20%20The%20segment%20angle%20is%20given%20by%20the%20matrix%20of%20the%20rotation%20from%20the%20laboratory%20coordinate%20system%20(%24G%24)%20to%20a%20coordinate%20system%20attached%20to%20the%20segment%2C%20and%20the%20joint%20angle%20by%20the%20matrix%20of%20the%20rotation%20from%20one%20segment's%20coordinate%20system%20(%24l_1%24)%20to%20the%20other's%20(%24l_2%24).%20So%20we%20compute%20two%20bases%2C%20one%20for%20each%20segment%2C%20and%20the%20joint%20angle%20comes%20from%20the%20product%20of%20the%20two%20rotation%20matrices.%0A%0A%20%20%20%20The%20description%20of%20a%20point%20P%20in%20the%20Global%20basis%2C%20given%20its%20description%20in%20the%20%24l_1%24%20basis%2C%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20x_p%5C%5C%0A%20%20%20%20y_p%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%20R_%7BGl_1%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20x_%7Bp_1%7D%5C%5C%0A%20%20%20%20y_%7Bp_1%7D%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20the%20description%20of%20the%20same%20point%20P%20in%20the%20Global%20basis%2C%20given%20its%20description%20in%20the%20%24l_2%24%20basis%2C%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20x_p%5C%5C%0A%20%20%20%20y_p%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%20R_%7BGl_2%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20x_%7Bp_2%7D%5C%5C%0A%20%20%20%20y_%7Bp_2%7D%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20So%20the%20description%20of%20P%20in%20the%20%24l_1%24%20basis%2C%20given%20its%20description%20in%20the%20%24l_2%24%20basis%2C%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20R_%7BGl_1%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20x_%7Bp_1%7D%5C%5C%0A%20%20%20%20y_%7Bp_1%7D%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20R_%7BGl_2%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20x_%7Bp_2%7D%5C%5C%0A%20%20%20%20y_%7Bp_2%7D%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cquad%20%5CLongrightarrow%20%5Cquad%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20x_%7Bp_1%7D%5C%5C%0A%20%20%20%20y_%7Bp_1%7D%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cunderbrace%7BR_%7BGl_1%7D%5E%7B-1%7DR_%7BGl_2%7D%7D_%7BR_%7Bl_1l_2%7D%7D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20x_%7Bp_2%7D%5C%5C%0A%20%20%20%20y_%7Bp_2%7D%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20the%20rotation%20matrix%20from%20%24l_2%24%20to%20%24l_1%24%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20R_%7Bl_1l_2%7D%20%3D%20R_%7BGl_1%7D%5E%7B-1%7DR_%7BGl_2%7D%20%3D%20R_%7BGl_1%7D%5E%7BT%7DR_%7BGl_2%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20rotation%20matrices%20of%20the%20two%20bases%20are%0A%0A%20%20%20%20%24%24%0A%20%20%20%20R_%7BGl_1%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos(%5Ctheta_1)%20%26-%5Csin(%5Ctheta_1)%5C%5C%0A%20%20%20%20%5Csin(%5Ctheta_1)%20%26%5Chphantom%7B-%7D%5Ccos(%5Ctheta_1)%0A%20%20%20%20%5Cend%7Bbmatrix%7D%2C%20%5Cquad%0A%20%20%20%20R_%7BGl_2%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos(%5Ctheta_2)%20%26-%5Csin(%5Ctheta_2)%5C%5C%0A%20%20%20%20%5Csin(%5Ctheta_2)%20%26%5Chphantom%7B-%7D%5Ccos(%5Ctheta_2)%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20so%20the%20rotation%20matrix%20from%20%24l_2%24%20to%20%24l_1%24%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7Baligned%7D%0A%20%20%20%20R_%7Bl_1l_2%7D%20%26%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos(%5Ctheta_1)%20%26%5Csin(%5Ctheta_1)%5C%5C%0A%20%20%20%20-%5Csin(%5Ctheta_1)%20%26%5Ccos(%5Ctheta_1)%0A%20%20%20%20%5Cend%7Bbmatrix%7D%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos(%5Ctheta_2)%20%26-%5Csin(%5Ctheta_2)%5C%5C%0A%20%20%20%20%5Csin(%5Ctheta_2)%20%26%5Chphantom%7B-%7D%5Ccos(%5Ctheta_2)%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%5C%5C%0A%20%20%20%20%26%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos(%5Ctheta_1)%5Ccos(%5Ctheta_2)%2B%5Csin(%5Ctheta_1)%5Csin(%5Ctheta_2)%20%26%5Ccos(%5Ctheta_2)%5Csin(%5Ctheta_1)-%5Ccos(%5Ctheta_1)%5Csin(%5Ctheta_2)%5C%5C%0A%20%20%20%20%5Ccos(%5Ctheta_1)%5Csin(%5Ctheta_2)-%5Ccos(%5Ctheta_2)%5Csin(%5Ctheta_1)%26%5Ccos(%5Ctheta_1)%5Ccos(%5Ctheta_2)%2B%5Csin(%5Ctheta_1)%5Csin(%5Ctheta_2)%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%5C%5C%0A%20%20%20%20%26%3D%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos(%5Ctheta_2-%5Ctheta_1)%20%26-%5Csin(%5Ctheta_2-%5Ctheta_1)%5C%5C%0A%20%20%20%20%5Csin(%5Ctheta_2-%5Ctheta_1)%20%26%5Chphantom%7B-%7D%5Ccos(%5Ctheta_2-%5Ctheta_1)%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cend%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20angle%20%24%5Ctheta_%7Bl_1l_2%7D%20%3D%20%5Ctheta_2-%5Ctheta_1%24%20is%20the%20angle%20between%20the%20two%20coordinate%20systems%2C%20and%20it%20is%20found%20from%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Ctheta_%7Bl_1l_2%7D%20%3D%20%5Carctan%5Cleft(%5Cfrac%7BR_%7Bl_1l_2%7D%5B1%2C0%5D%7D%7BR_%7Bl_1l_2%7D%5B0%2C0%5D%7D%5Cright)%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%20Here%20is%20an%20example%20with%20the%20two%20segments%20of%20%5BAngular%20kinematics%20in%20a%20plane%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_angular_2d.py)%3A%20segment%201%20from%20%24(0%2C%200)%24%20to%20%24(1%2C%201)%24%2C%20and%20segment%202%20from%20%24(2.1%2C%200)%24%20to%20%24(1.1%2C%201)%24.%20Each%20segment%20gives%20one%20axis%20of%20its%20basis.%20For%20the%20second%20axis%20we%20need%20a%20point%20on%20a%20line%20perpendicular%20to%20the%20segment%2C%20and%20there%20is%20a%20neat%20way%20to%20get%20one%3A%20turn%20the%20vector%20of%20the%20segment%2C%20%24(%5CDelta%20x%2C%20%5CDelta%20y)%24%2C%20by%20%2490%5E%5Ccirc%24%2C%20which%20gives%20%24(-%5CDelta%20y%2C%20%5CDelta%20x)%24.%20That%20is%20the%20rotation%20matrix%20of%20%2490%5E%5Ccirc%24%20at%20work.%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%20x1%2C%20y1%2C%20x2%2C%20y2%20%3D%200%2C%200%2C%201%2C%201%20%20%23%20points%20on%20segment%201%0A%20%20%20%20x3%2C%20y3%2C%20x4%2C%20y4%20%3D%201.1%2C%201%2C%202.1%2C%200%20%20%23%20points%20on%20segment%202%0A%0A%20%20%20%20%23%20A%20point%20on%20the%20line%20through%20the%20first%20point%20of%20each%20segment%2C%20perpendicular%20to%20it%0A%20%20%20%20xl1%20%3D%20x1%20-%20(y2%20-%20y1)%3B%20yl1%20%3D%20y1%20%2B%20(x2%20-%20x1)%20%20%23%20perpendicular%20to%20segment%201%0A%20%20%20%20xl2%20%3D%20x4%20-%20(y3%20-%20y4)%3B%20yl2%20%3D%20y4%20%2B%20(x3%20-%20x4)%20%20%23%20perpendicular%20to%20segment%202%0A%20%20%20%20return%20x1%2C%20x2%2C%20x3%2C%20x4%2C%20xl1%2C%20xl2%2C%20y1%2C%20y2%2C%20y3%2C%20y4%2C%20yl1%2C%20yl2%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%20these%20points%2C%20we%20can%20create%20a%20basis%20for%20each%20segment%20and%20the%20corresponding%20rotation%20matrices%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20x1%2C%20x2%2C%20x3%2C%20x4%2C%20xl1%2C%20xl2%2C%20y1%2C%20y2%2C%20y3%2C%20y4%2C%20yl1%2C%20yl2)%3A%0A%20%20%20%20b1x%20%3D%20np.array(%5Bx2%20-%20x1%2C%20y2%20-%20y1%5D)%0A%20%20%20%20b1x%20%3D%20b1x%20%2F%20np.linalg.norm(b1x)%20%20%23%20versor%20x%20of%20basis%201%0A%20%20%20%20b1y%20%3D%20np.array(%5Bxl1%20-%20x1%2C%20yl1%20-%20y1%5D)%0A%20%20%20%20b1y%20%3D%20b1y%20%2F%20np.linalg.norm(b1y)%20%20%23%20versor%20y%20of%20basis%201%0A%20%20%20%20b2x%20%3D%20np.array(%5Bx3%20-%20x4%2C%20y3%20-%20y4%5D)%0A%20%20%20%20b2x%20%3D%20b2x%20%2F%20np.linalg.norm(b2x)%20%20%23%20versor%20x%20of%20basis%202%0A%20%20%20%20b2y%20%3D%20np.array(%5Bxl2%20-%20x4%2C%20yl2%20-%20y4%5D)%0A%20%20%20%20b2y%20%3D%20b2y%20%2F%20np.linalg.norm(b2y)%20%20%23%20versor%20y%20of%20basis%202%0A%0A%20%20%20%20RGl1%20%3D%20np.array(%5Bb1x%2C%20b1y%5D).T%20%20%23%20rotation%20matrix%20from%20segment%201%20to%20the%20laboratory%0A%20%20%20%20RGl2%20%3D%20np.array(%5Bb2x%2C%20b2y%5D).T%20%20%23%20rotation%20matrix%20from%20segment%202%20to%20the%20laboratory%0A%0A%20%20%20%20print(%22Rotation%20matrix%20from%20segment%201%20to%20Global%3A%5Cn%22%2C%20RGl1)%0A%20%20%20%20print(%22Rotation%20matrix%20from%20segment%202%20to%20Global%3A%5Cn%22%2C%20RGl2)%0A%20%20%20%20return%20RGl1%2C%20RGl2%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%20Now%20the%20segment%20and%20joint%20angles%20are%20simple%20matrix%20operations.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20the%20three%20angles%3A%20of%20segment%201%2C%20of%20segment%202%2C%20and%20of%20the%20joint%20between%20them.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RGl1%2C%20RGl2%2C%20np)%3A%0A%20%20%20%20print(%22Rotation%20matrix%20for%20segment%201%3A%5Cn%22%2C%20RGl1)%0A%20%20%20%20print(%22%5CnRotation%20angle%20of%20segment%201%3A%22%2C%20np.arctan2(RGl1%5B1%2C%200%5D%2C%20RGl1%5B0%2C%200%5D)%20*%20180%20%2F%20np.pi)%0A%20%20%20%20print(%22%5CnRotation%20matrix%20for%20segment%202%3A%5Cn%22%2C%20RGl2)%0A%20%20%20%20print(%22%5CnRotation%20angle%20of%20segment%202%3A%22%2C%20np.arctan2(RGl2%5B1%2C%200%5D%2C%20RGl2%5B0%2C%200%5D)%20*%20180%20%2F%20np.pi)%0A%0A%20%20%20%20_Rl1l2%20%3D%20RGl1.T%20%40%20RGl2%20%20%23%20Rl1l2%20%3D%20Rl1G%20RGl2%0A%0A%20%20%20%20print(%22%5CnJoint%20rotation%20matrix%20(Rl1l2%20%3D%20Rl1G%20RGl2)%3A%5Cn%22%2C%20_Rl1l2)%0A%20%20%20%20print(%22%5CnJoint%20angle%3A%22%2C%20np.arctan2(_Rl1l2%5B1%2C%200%5D%2C%20_Rl1l2%5B0%2C%200%5D)%20*%20180%20%2F%20np.pi)%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%20%2445%5E%5Ccirc%24%2C%20%24135%5E%5Ccirc%24%20and%20%2490%5E%5Ccirc%24%20as%20obtained%20with%20trigonometry%20in%20%5BAngular%20kinematics%20in%20a%20plane%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_angular_2d.py).%20(Python%20prints%20%24-0.%24%20for%20a%20number%20that%20is%20zero%20but%20carries%20a%20negative%20sign%20from%20rounding%3B%20it%20is%20harmless.)%0A%0A%20%20%20%20Why%20go%20to%20the%20trouble%20of%20matrices%20for%20something%20a%20subtraction%20of%20angles%20already%20did%3F%20Because%20the%20matrix%20method%20does%20not%20care%20how%20the%20bases%20were%20built%2C%20needs%20no%20rule%20about%20which%20end%20of%20a%20segment%20points%20where%20once%20the%20bases%20are%20defined%2C%20and%20carries%20over%20unchanged%20to%20three%20dimensions%2C%20where%20angles%20can%20no%20longer%20simply%20be%20subtracted.%0A%0A%20%20%20%20**Guiding%20questions%201.**%0A%0A%20%20%20%201.%20Compute%20%24R_%7Bl_2l_1%7D%24%20instead%20of%20%24R_%7Bl_1l_2%7D%24.%20What%20angle%20does%20it%20give%2C%20and%20why%3F%0A%20%20%20%202.%20Reverse%20the%20direction%20of%20segment%202's%20x%20axis%2C%20from%20marker%203%20to%20marker%204%20instead%20of%20from%20marker%204%20to%20marker%203.%20What%20happens%20to%20the%20joint%20angle%3F%20What%20happens%20to%20it%20in%20the%20trigonometric%20method%3F%0A%20%20%20%203.%20The%20joint%20angle%20came%20from%20%24R_%7BGl_1%7D%5ET%20R_%7BGl_2%7D%24.%20Would%20%24R_%7BGl_2%7D%20R_%7BGl_1%7D%5ET%24%20give%20the%20same%20answer%20in%20a%20plane%3F%20Do%20you%20expect%20that%20to%20hold%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%23%20Example%3A%20a%20knee%20angle%20that%20jumps%20by%20360%C2%B0%0A%0A%20%20%20%20The%20angles%20above%20were%20computed%20for%20a%20single%20instant.%20In%20a%20real%20analysis%20they%20are%20computed%20for%20every%20frame%2C%20so%20let's%20write%20the%20recipe%20as%20a%20function%20that%20works%20on%20whole%20arrays%20of%20frames%3A%20the%20local%20%24x%24%20axis%20points%20from%20one%20joint%20(or%20marker)%20to%20the%20next%2C%20and%20the%20local%20%24y%24%20axis%20is%20%24x%24%20turned%20%2490%5E%5Ccirc%24%20counterclockwise%2C%20as%20in%20the%20example%20above.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20segment_rotation_2d(origin%2C%20axis_point)%3A%0A%20%20%20%20%22%22%22Rotation%20matrix%20R_Gl%20of%20a%20planar%20segment%20from%20two%20of%20its%20markers.%0A%0A%20%20%20%20The%20local%20x%20axis%20points%20from%20%60origin%60%20to%20%60axis_point%60%2C%20and%20the%20local%20y%20axis%0A%20%20%20%20is%20x%20turned%20by%2090%20degrees%20counterclockwise.%20The%20versors%20are%20the%20columns%20of%0A%20%20%20%20R_Gl.%20Works%20for%20one%20frame%20or%20for%20arrays%20of%20frames%20(one%20position%20per%20row).%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20d%20%3D%20np.asarray(axis_point%2C%20dtype%3Dfloat)%20-%20np.asarray(origin%2C%20dtype%3Dfloat)%0A%20%20%20%20ex%20%3D%20d%20%2F%20np.linalg.norm(d%2C%20axis%3D-1%2C%20keepdims%3DTrue)%0A%20%20%20%20ey%20%3D%20np.stack((-ex%5B...%2C%201%5D%2C%20ex%5B...%2C%200%5D)%2C%20axis%3D-1)%0A%20%20%20%20return%20np.stack((ex%2C%20ey)%2C%20axis%3D-1)%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%20Here%20is%20a%20movement%20in%20which%20the%20difference%20between%20the%20two%20methods%20stops%20being%20academic.%20A%20kick%2C%20seen%20from%20the%20side%2C%20simulated%20at%20100%20Hz%20for%20one%20second%3A%20the%20knee%20flexes%20by%20up%20to%20%24130%5E%5Ccirc%24%20while%20the%20hip%20flexes%20by%20up%20to%20%2415%5E%5Ccirc%24.%20With%20%24X%24%20pointing%20forward%2C%20the%20thigh%20starts%20straight%20down%2C%20at%20%24-90%5E%5Ccirc%24%2C%20and%20the%20flexing%20knee%20carries%20the%20shank%20backward%2C%20so%20the%20shank's%20angle%20*decreases*%2C%20down%20to%20%24-75%5E%5Ccirc%20-%20130%5E%5Ccirc%20%3D%20-205%5E%5Ccirc%24%20at%20the%20peak.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20think%20about%20that%20number.%20What%20angle%20will%20%60arctan2%60%2C%20whose%20answers%20lie%20between%20%24-180%5E%5Ccirc%24%20and%20%24180%5E%5Ccirc%24%2C%20report%20for%20a%20shank%20pointing%20at%20%24-205%5E%5Ccirc%24%3F%20And%20what%20will%20the%20subtraction%20of%20the%20two%20segment%20angles%20give%20for%20the%20knee%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt)%3A%0A%20%20%20%20_t%20%3D%20np.linspace(0%2C%201%2C%20101)%20%20%23%20s%2C%20100%20Hz%0A%20%20%20%20_thigh%20%3D%20np.radians(-90%20%2B%2015%20*%20np.sin(np.pi%20*%20_t))%20%20%23%20the%20hip%20flexes%20up%20to%2015%20degrees%0A%20%20%20%20_flexion%20%3D%20np.radians(130%20*%20np.sin(np.pi%20*%20_t))%20%20%23%20the%20knee%20flexes%20up%20to%20130%20degrees%0A%20%20%20%20_hip%20%3D%20np.column_stack((np.zeros_like(_t)%2C%20np.full_like(_t%2C%200.9)))%0A%20%20%20%20_knee%20%3D%20_hip%20%2B%200.42%20*%20np.column_stack((np.cos(_thigh)%2C%20np.sin(_thigh)))%0A%20%20%20%20_ankle%20%3D%20_knee%20%2B%200.40%20*%20np.column_stack((np.cos(_thigh%20-%20_flexion)%2C%20np.sin(_thigh%20-%20_flexion)))%0A%0A%20%20%20%20def%20_segment_angle(R)%3A%0A%20%20%20%20%20%20%20%20return%20np.degrees(np.arctan2(R%5B...%2C%201%2C%200%5D%2C%20R%5B...%2C%200%2C%200%5D))%0A%0A%20%20%20%20_R_thigh%20%3D%20segment_rotation_2d(_hip%2C%20_knee)%20%20%23%20one%202x2%20matrix%20per%20frame%0A%20%20%20%20_R_shank%20%3D%20segment_rotation_2d(_knee%2C%20_ankle)%0A%20%20%20%20_by_subtraction%20%3D%20_segment_angle(_R_shank)%20-%20_segment_angle(_R_thigh)%0A%20%20%20%20_by_matrices%20%3D%20_segment_angle(np.swapaxes(_R_thigh%2C%20-1%2C%20-2)%20%40%20_R_shank)%20%20%23%20R_l1G%20R_Gl2%20in%20every%20frame%0A%0A%20%20%20%20_i%20%3D%2050%20%20%23%20t%20%3D%200.5%20s%2C%20the%20peak%20of%20the%20flexion%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22At%20t%20%3D%20%7B_t%5B_i%5D%3A.1f%7D%20s%2C%20arctan2%20gives%20the%20shank%20%7B_segment_angle(_R_shank)%5B_i%5D%3A.1f%7D%20degrees%22%0A%20%20%20%20%20%20%20%20f%22%20and%20the%20thigh%20%7B_segment_angle(_R_thigh)%5B_i%5D%3A.1f%7D%20degrees%22%0A%20%20%20%20)%0A%20%20%20%20print(f%22Knee%20angle%20by%20subtraction%3A%20%7B_by_subtraction%5B_i%5D%3A.1f%7D%20degrees%3B%20with%20rotation%20matrices%3A%20%7B_by_matrices%5B_i%5D%3A.1f%7D%20degrees%22)%0A%20%20%20%20print(f%22Frames%20in%20which%20the%20two%20methods%20disagree%3A%20%7Bnp.sum(~np.isclose(_by_subtraction%2C%20_by_matrices))%7D%20of%20%7B_t.size%7D%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(_t%2C%20_by_subtraction%2C%20color%3D%22tab%3Ared%22%2C%20linewidth%3D2%2C%20linestyle%3D%22--%22%2C%20label%3D%22subtraction%20of%20segment%20angles%22)%0A%20%20%20%20_ax.plot(_t%2C%20_by_matrices%2C%20color%3D%22tab%3Ablue%22%2C%20linewidth%3D2%2C%20label%3Dr%22rotation%20matrices%2C%20%24R_%7Bl_1G%7DR_%7BGl_2%7D%24%22)%0A%20%20%20%20_ax.axhline(0%2C%20color%3D%220.7%22%2C%20linewidth%3D1)%0A%20%20%20%20_ax.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Knee%20angle%20%5Bdegrees%5D%22)%0A%20%20%20%20_ax.set_title(%22Knee%20angle%20during%20a%20simulated%20kick%22)%0A%20%20%20%20_ax.legend(loc%3D%22center%20right%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%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%60arctan2%60%20reports%20the%20shank%20at%20%24%2B155%5E%5Ccirc%24%2C%20the%20same%20direction%20as%20%24-205%5E%5Ccirc%24%20but%20on%20the%20other%20side%20of%20the%20%24%5Cpm%20180%5E%5Ccirc%24%20cut.%20The%20subtraction%20then%20gives%20a%20knee%20bent%20by%20%24230%5E%5Ccirc%24%20the%20wrong%20way%2C%20and%20it%20jumps%20by%20almost%20%24360%5E%5Ccirc%24%20each%20time%20the%20shank%20passes%20straight%20backward.%20It%20is%20wrong%20in%2043%20of%20the%20101%20frames.%20The%20rotation%20matrix%20of%20the%20joint%20never%20looks%20at%20the%20two%20segment%20angles%20separately%2C%20only%20at%20the%20rotation%20between%20the%20segments%2C%20and%20it%20gives%20a%20smooth%20curve%20with%20a%20minimum%20of%20%24-130%5E%5Ccirc%24%3A%20the%20flexion%20we%20simulated%2C%20negative%20because%20flexing%20the%20knee%20turns%20the%20shank%20clockwise%20in%20this%20view.%0A%0A%20%20%20%20Note%20%60np.swapaxes(R%2C%20-1%2C%20-2)%60%20in%20the%20code.%20With%20one%20matrix%20per%20frame%2C%20%60R.T%60%20would%20transpose%20the%20whole%20array%3B%20swapping%20the%20last%20two%20axes%20transposes%20each%20matrix.%20The%20subtraction%20can%20also%20be%20repaired%20after%20the%20fact%20with%20%60np.unwrap%60%2C%20provided%20the%20frames%20are%20close%20enough%20together.%20The%20matrix%20method%20needs%20no%20repair%20as%20long%20as%20the%20joint%20itself%20turns%20by%20less%20than%20%24180%5E%5Ccirc%24.%0A%0A%20%20%20%20**Exercise%203.**%20In%20one%20frame%20of%20a%20walking%20trial%2C%20the%20hip%2C%20knee%20and%20ankle%20joint%20centres%20are%20at%20%24(0%2C%201.00)%24%2C%20%24(0.25%2C%200.60)%24%20and%20%24(0.05%2C%200.22)%24%20m%2C%20with%20%24X%24%20forward%20and%20%24Y%24%20up.%20Build%20the%20thigh's%20coordinate%20system%20from%20the%20hip%20to%20the%20knee%20and%20the%20shank's%20from%20the%20knee%20to%20the%20ankle%20with%20%60segment_rotation_2d%60%2C%20and%20calculate%20the%20angle%20of%20each%20segment%20and%20of%20the%20knee.%20Is%20the%20knee%20flexed%2C%20and%20by%20how%20much%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_hip%2C%20_knee%2C%20_ankle%20%3D%20np.array(%5B0%2C%201.00%5D)%2C%20np.array(%5B0.25%2C%200.60%5D)%2C%20np.array(%5B0.05%2C%200.22%5D)%0A%20%20%20%20_R_thigh%20%3D%20segment_rotation_2d(_hip%2C%20_knee)%0A%20%20%20%20_R_shank%20%3D%20segment_rotation_2d(_knee%2C%20_ankle)%0A%20%20%20%20_R_knee%20%3D%20_R_thigh.T%20%40%20_R_shank%20%20%23%20rotation%20of%20the%20shank%20relative%20to%20the%20thigh%0A%20%20%20%20_thigh%2C%20_shank%2C%20_joint%20%3D%20(np.degrees(np.arctan2(_R%5B1%2C%200%5D%2C%20_R%5B0%2C%200%5D))%20for%20_R%20in%20(_R_thigh%2C%20_R_shank%2C%20_R_knee))%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.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%60%60%60python%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22R_thigh%20%3D%20segment_rotation_2d(hip%2C%20knee)%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22R_shank%20%3D%20segment_rotation_2d(knee%2C%20ankle)%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22R_knee%20%3D%20R_thigh.T%20%40%20R_shank%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22angle%20%3D%20np.degrees(np.arctan2(R%5B1%2C%200%5D%2C%20R%5B0%2C%200%5D))%20%20%23%20for%20each%20R%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%60%60%60%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22The%20thigh%20is%20at%20%7B_thigh%3A.1f%7D%C2%B0%20and%20the%20shank%20at%20%7B_shank%3A.1f%7D%C2%B0%2C%20and%20the%20rotation%20of%20the%20shank%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22relative%20to%20the%20thigh%20is%20%7B_joint%3A.1f%7D%C2%B0.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22The%20sign%20is%20negative%20because%20the%20shank%20is%20turned%20clockwise%20from%20the%20thigh%2C%20which%20in%20this%20view%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22with%20%24X%24%20forward%2C%20is%20flexion%3A%20the%20knee%20is%20flexed%20by%20%7Babs(_joint)%3A.1f%7D%C2%B0.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22Here%20the%20subtraction%20of%20the%20segment%20angles%20gives%20the%20same%20%7B_shank%20-%20_thigh%3A.1f%7D%C2%B0%2C%20because%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22neither%20segment%20points%20near%20the%20%24%5C%5Cpm%20180%C2%B0%24%20cut.%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%23%20Kinematic%20chain%20in%20a%20plane%20(2D)%0A%0A%20%20%20%20The%20fact%20that%20we%20simply%20multiplied%20rotation%20matrices%20to%20obtain%20the%20rotation%20of%20one%20segment%20relative%20to%20another%20is%20powerful%2C%20and%20it%20generalizes%20to%20any%20number%20of%20segments.%20Consider%20a%20serial%20kinematic%20chain%20with%20links%20%241%2C%202%2C%20%5Cdots%2C%20n%24%2C%20and%20call%20the%20base%2C%20or%20the%20laboratory%2C%20link%20%240%24.%20With%20the%20notation%20of%20this%20notebook%2C%20where%20%24%5Cmathbf%7BR%7D_%7Bab%7D%24%20takes%20coordinates%20in%20%24b%24%20to%20coordinates%20in%20%24a%24%2C%20the%20rotation%20matrix%20of%20the%20last%20link%20with%20respect%20to%20the%20base%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR%7D_%7B0n%7D%20%3D%20%5Cmathbf%7BR%7D_%7B01%7D%5Cmathbf%7BR%7D_%7B12%7D%20%5Ccdots%20%5Cmathbf%7BR%7D_%7Bn-1%2Cn%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20where%20each%20matrix%20in%20the%20product%20is%20the%20rotation%20of%20one%20link%20with%20respect%20to%20the%20previous%20one.%20Its%20inverse%2C%20from%20the%20base%20to%20the%20last%20link%2C%20is%20the%20product%20of%20the%20transposes%20in%20the%20reverse%20order%3A%20%24%5Cmathbf%7BR%7D_%7Bn0%7D%20%3D%20%5Cmathbf%7BR%7D_%7Bn%2Cn-1%7D%5Cmathbf%7BR%7D_%7Bn-1%2Cn-2%7D%20%5Ccdots%20%5Cmathbf%7BR%7D_%7B2%2C1%7D%5Cmathbf%7BR%7D_%7B1%2C0%7D%24.%0A%0A%20%20%20%20For%20instance%2C%20consider%20a%20kinematic%20chain%20with%20two%20links%3A%20link%201%20is%20rotated%20by%20%24%5Calpha_1%24%20with%20respect%20to%20the%20base%20(0)%2C%20and%20link%202%20is%20rotated%20by%20%24%5Calpha_2%24%20with%20respect%20to%20link%201.%20With%20SymPy%2C%20the%20rotation%20matrices%20of%20link%202%20with%20respect%20to%20link%201%2C%20%24%5Cmathbf%7BR%7D_%7B12%7D%24%2C%20and%20of%20link%201%20with%20respect%20to%20the%20base%2C%20%24%5Cmathbf%7BR%7D_%7B01%7D%24%2C%20are%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%20import%20sympy%20as%20sym%0A%0A%20%20%20%20return%20(sym%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo%2C%20sym)%3A%0A%20%20%20%20a1%2C%20a2%20%3D%20sym.symbols(%22alpha1%20alpha2%22)%0A%0A%20%20%20%20R12%20%3D%20sym.Matrix(%5B%5Bsym.cos(a2)%2C%20-sym.sin(a2)%5D%2C%20%5Bsym.sin(a2)%2C%20sym.cos(a2)%5D%5D)%0A%20%20%20%20R01%20%3D%20sym.Matrix(%5B%5Bsym.cos(a1)%2C%20-sym.sin(a1)%5D%2C%20%5Bsym.sin(a1)%2C%20sym.cos(a1)%5D%5D)%0A%0A%20%20%20%20mo.md(rf%22%24%24%5Cmathbf%7B%7BR_%7B%7B12%7D%7D%7D%7D%20%3D%20%7Bsym.latex(R12)%7D%2C%20%5Cqquad%20%5Cmathbf%7B%7BR_%7B%7B01%7D%7D%7D%7D%20%3D%20%7Bsym.latex(R01)%7D%24%24%22)%0A%20%20%20%20return%20R01%2C%20R12%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%20rotation%20matrix%20of%20link%202%20with%20respect%20to%20the%20base%2C%20%24%5Cmathbf%7BR%7D_%7B02%7D%24%2C%20is%20simply%20%24%5Cmathbf%7BR%7D_%7B01%7D%5Cmathbf%7BR%7D_%7B12%7D%24%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R01%2C%20R12%2C%20mo%2C%20sym)%3A%0A%20%20%20%20R02%20%3D%20R01%20*%20R12%0A%0A%20%20%20%20mo.md(rf%22%24%24%5Cmathbf%7B%7BR_%7B%7B02%7D%7D%7D%7D%20%3D%20%7Bsym.latex(R02)%7D%24%24%22)%0A%20%20%20%20return%20(R02%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%20which%20simplifies%20to%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R02%2C%20mo%2C%20sym)%3A%0A%20%20%20%20mo.md(rf%22%24%24%5Cmathbf%7B%7BR_%7B%7B02%7D%7D%7D%7D%20%3D%20%7Bsym.latex(sym.simplify(R02))%7D%24%24%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%20A%20rotation%20by%20%24%5Calpha_1%20%2B%20%5Calpha_2%24%2C%20as%20expected%3A%20in%20a%20plane%2C%20rotations%20about%20the%20axis%20perpendicular%20to%20it%20simply%20add%20up.%20Which%20also%20means%20the%20order%20does%20not%20matter.%20The%20difference%20%24%5Cmathbf%7BR%7D_%7B01%7D%5Cmathbf%7BR%7D_%7B12%7D%20-%20%5Cmathbf%7BR%7D_%7B12%7D%5Cmathbf%7BR%7D_%7B01%7D%24%20is%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R01%2C%20R12%2C%20sym)%3A%0A%20%20%20%20sym.simplify(R01%20*%20R12%20-%20R12%20*%20R01)%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%20Zero%3A%20in%20a%20plane%2C%20rotation%20matrices%20commute.%20Enjoy%20it%20while%20it%20lasts.%20In%20three-dimensional%20motion%20analysis%2C%20rotations%20happen%20about%20different%20axes%2C%20and%20the%20order%20of%20the%20product%20changes%20the%20result%3B%20that%20needs%20special%20care%2C%20as%20%5BRigid-body%20transformations%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_3d.py)%20shows.%20%5BKinematic%20chain%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematic_chain.py)%20puts%20chains%20of%20links%20to%20work.%0A%0A%20%20%20%20**Challenge%201.**%20Hold%20a%20book%20in%20front%20of%20you.%20Turn%20it%20%2490%5E%5Ccirc%24%20about%20a%20vertical%20axis%20and%20then%20%2490%5E%5Ccirc%24%20about%20a%20horizontal%20axis%20pointing%20to%20your%20right.%20Start%20again%20from%20the%20same%20position%20and%20do%20the%20two%20rotations%20in%20the%20opposite%20order.%20Do%20you%20end%20up%20in%20the%20same%20place%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%20Translation%20and%20rotation%0A%0A%20%20%20%20Consider%20now%20a%20local%20coordinate%20system%20that%20is%20both%20translated%20and%20rotated%20in%20relation%20to%20the%20Global%20coordinate%20system%2C%20with%20a%20point%20described%20in%20both%2C%20as%20in%20the%20figure%20below%20(once%20again%2C%20this%20is%20equivalent%20to%20describing%20the%20translation%20and%20rotation%20between%20two%20rigid%20bodies).%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%2Ftransrot2D.png%3Fraw%3D1%22%20width%3D345%20alt%3D%22translation%20and%20rotation%202D%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.%20A%20point%20in%20two-dimensional%20space%20represented%20in%20two%20coordinate%20systems%2C%20with%20one%20system%20translated%20and%20rotated.%3C%2Fspan%3E%0A%0A%20%20%20%20The%20position%20of%20point%20%24%5Cmathbf%7BP%7D%24%2C%20originally%20described%20in%20the%20local%20coordinate%20system%2C%20described%20in%20the%20Global%20coordinate%20system%20in%20vector%20form%20is%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%20and%20in%20matrix%20form%2C%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%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%20%5Cmathbf%7BL_%7BX%7D%7D%20%5C%5C%20%5Cmathbf%7BL_%7BY%7D%7D%20%5Cend%7Bbmatrix%7D%20%2B%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%0A%20%20%20%20%5Cend%7Bbmatrix%7D%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%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20This%20means%20that%20we%20first%20rotate%20the%20coordinates%20from%20the%20local%20to%20the%20Global%20orientation%20(%22disrotate%22%20the%20local%20coordinate%20system)%20and%20then%20correct%20for%20the%20translation%20between%20the%20two%20coordinate%20systems.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20whether%20the%20order%20matters.%20Take%20the%20example%20of%20the%20three%20markers%20above%2C%20%24%5Cmathbf%7BL_%7BGl%7D%7D%20%3D%20%5B1%2C%201%5D%24%20and%20a%20rotation%20of%20%2490%5E%5Ccirc%24%2C%20and%20the%20point%20%24%5Cmathbf%7BP_l%7D%3D%5B1%2C1%5D%24.%20What%20would%20you%20get%20by%20adding%20the%20translation%20first%20and%20rotating%20afterwards%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(LGl%2C%20R_basis%2C%20np)%3A%0A%20%20%20%20_Pl%20%3D%20np.array(%5B%5B1%2C%201%5D%5D).T%0A%0A%20%20%20%20print(%22Rotate%2C%20then%20translate%3A%20LGl%20%2B%20RGl%20Pl%20%20%20%3D%22%2C%20(LGl%20%2B%20R_basis%20%40%20_Pl).ravel())%0A%20%20%20%20print(%22Translate%2C%20then%20rotate%3A%20RGl%20(Pl%20%2B%20LGl)%20%3D%22%2C%20(R_basis%20%40%20(_Pl%20%2B%20LGl)).ravel())%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%20Different%20answers%2C%20and%20only%20the%20first%20is%20right.%20We%20cannot%20invert%20the%20order%3A%20the%20position%20of%20the%20point%20is%20expressed%20in%20the%20local%20coordinate%20system%2C%20and%20adding%20it%20to%20the%20translation%2C%20a%20vector%20expressed%20in%20the%20Global%20coordinate%20system%2C%20mixes%20two%20coordinate%20systems.%20Vectors%20can%20only%20be%20added%20once%20they%20are%20expressed%20in%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%7Baligned%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%26%20%5Cimplies%0A%20%20%20%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D(%5Cmathbf%7BP_G%7D%20-%20%5Cmathbf%7BL_G%7D)%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5E%7B-1%7D%7D%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%20%5C%5C%0A%20%20%20%20%26%20%5Cimplies%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%5Cmathbf%7BR_%7BGl%7D%5ET%7D%5Cleft(%5Cmathbf%7BP_G%7D-%5Cmathbf%7BL_G%7D%5Cright)%0A%20%20%20%20%5Cquad%20%5Ctext%7Bor%7D%20%5Cquad%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%7Baligned%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20To%20go%20from%20the%20Global%20to%20the%20local%20coordinate%20system%2C%20we%20first%20translate%20and%20then%20rotate%3A%20the%20subtraction%20happens%20while%20both%20vectors%20are%20still%20in%20Global%20coordinates.%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%3A%20where%20under%20the%20foot%20is%20the%20centre%20of%20pressure%3F%0A%0A%20%20%20%20A%20force%20plate%20reports%20the%20centre%20of%20pressure%20(COP)%2C%20the%20point%20where%20the%20resultant%20ground%20reaction%20force%20acts%2C%20in%20the%20laboratory's%20coordinate%20system.%20On%20its%20own%20that%20says%20little%20about%20the%20foot%3A%20the%20same%20laboratory%20coordinates%20can%20be%20under%20the%20heel%20in%20one%20step%20and%20under%20the%20toes%20in%20the%20next.%20What%20we%20want%20is%20the%20COP%20*relative%20to%20the%20foot*%2C%20and%20that%20is%20a%20Global-to-local%20transformation.%0A%0A%20%20%20%20Look%20at%20the%20floor%20from%20above%2C%20with%20%24X%24%20pointing%20in%20the%20direction%20of%20walking%20and%20%24Y%24%20to%20the%20left.%20Markers%20on%20the%20heel%20and%20on%20the%20head%20of%20the%20second%20metatarsal%20of%20a%20right%20foot%20are%20at%20%24(0.500%2C%200.100)%24%20and%20%24(0.740%2C%200.140)%24%20m.%20The%20foot's%20coordinate%20system%20has%20its%20origin%20at%20the%20heel%20marker%2C%20its%20%24x%24%20axis%20along%20the%20foot%2C%20towards%20the%20toe%20marker%2C%20and%20its%20%24y%24%20axis%20turned%20%2490%5E%5Ccirc%24%20counterclockwise%20from%20%24x%24%2C%20which%20for%20a%20right%20foot%20points%20medially.%20The%20force%20plate%20reports%20the%20COP%20at%20three%20instants%20of%20the%20stance%20phase%3A%0A%0A%20%20%20%20%7C%20instant%20%7C%20COP%20in%20the%20laboratory%20%5Bm%5D%20%7C%0A%20%20%20%20%7C---%7C---%7C%0A%20%20%20%20%7C%20heel%20strike%20%7C%20(0.515%2C%200.098)%20%7C%0A%20%20%20%20%7C%20midstance%20%7C%20(0.615%2C%200.112)%20%7C%0A%20%20%20%20%7C%20push-off%20%7C%20(0.730%2C%200.146)%20%7C%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20look%20only%20at%20the%20laboratory%20coordinates.%20At%20midstance%2C%20is%20the%20COP%20on%20the%20medial%20or%20on%20the%20lateral%20side%20of%20the%20line%20from%20the%20heel%20marker%20to%20the%20toe%20marker%3F%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_heel%20%3D%20np.array(%5B0.500%2C%200.100%5D)%20%20%23%20heel%20marker%20%5Bm%5D%2C%20seen%20from%20above%0A%20%20%20%20_toe%20%3D%20np.array(%5B0.740%2C%200.140%5D)%20%20%23%20marker%20on%20the%20head%20of%20the%20second%20metatarsal%20%5Bm%5D%0A%20%20%20%20_R_foot%20%3D%20segment_rotation_2d(_heel%2C%20_toe)%0A%20%20%20%20_length%20%3D%20np.linalg.norm(_toe%20-%20_heel)%0A%0A%20%20%20%20print(f%22The%20foot%20is%20turned%20%7Bnp.degrees(np.arctan2(_R_foot%5B1%2C%200%5D%2C%20_R_foot%5B0%2C%200%5D))%3A.1f%7D%20degrees%20from%20the%20direction%20of%20walking%22)%0A%20%20%20%20for%20_instant%2C%20_cop%20in%20%5B(%22heel%20strike%22%2C%20%5B0.515%2C%200.098%5D)%2C%20(%22midstance%22%2C%20%5B0.615%2C%200.112%5D)%2C%20(%22push-off%22%2C%20%5B0.730%2C%200.146%5D)%5D%3A%0A%20%20%20%20%20%20%20%20_x%2C%20_y%20%3D%20_R_foot.T%20%40%20(np.array(_cop)%20-%20_heel)%20%20%23%20Global%20to%20local%0A%20%20%20%20%20%20%20%20print(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%7B_instant%3A12s%7D%20COP%20at%20%7B100%20*%20_x%20%2F%20_length%3A4.1f%7D%25%20of%20the%20heel-toe%20distance%2C%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%20%7B100%20*%20abs(_y)%3A.1f%7D%20cm%20%7B'medial'%20if%20_y%20%3E%200%20else%20'lateral'%7D%20to%20the%20foot's%20axis%22%0A%20%20%20%20%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%20In%20the%20laboratory%2C%20the%20midstance%20COP%2C%20at%20%24Y%20%3D%200.112%24%20m%2C%20is%20to%20the%20left%20of%20the%20heel%20marker%2C%20which%20for%20a%20right%20foot%20is%20the%20medial%20side.%20In%20the%20foot's%20coordinate%20system%20it%20is%200.7%20cm%20*lateral*.%20The%20foot%20is%20turned%20out%20by%20%249.5%5E%5Ccirc%24%2C%20so%20its%20axis%20also%20runs%20to%20the%20left%2C%20and%20faster%20than%20the%20COP%20does.%20Over%20the%20stance%20phase%2C%20the%20COP%20moves%20from%20just%20lateral%20of%20the%20axis%20at%20the%20heel%20to%20just%20medial%20of%20it%20under%20the%20forefoot%2C%20the%20typical%20roll%20of%20the%20foot%20in%20walking%2C%20and%20that%20pattern%20only%20appears%20in%20the%20foot's%20coordinate%20system.%0A%0A%20%20%20%20**Exercise%204.**%20The%20same%20force%20plate%20measures%20the%20ground%20reaction%20force%20on%20a%20runner's%20foot%2C%20now%20in%20the%20sagittal%20plane%3A%20%24%5Cmathbf%7BF_G%7D%20%3D%20%5B120%2C%20680%5D%24%20N%2C%20with%20%24X%24%20forward%20and%20%24Y%24%20up.%20The%20shank's%20coordinate%20system%20has%20its%20origin%20at%20the%20ankle%2C%209%20cm%20above%20the%20floor%2C%20its%20%24x%24%20axis%20along%20the%20shank%20from%20the%20ankle%20to%20the%20knee%2C%20inclined%20%2420%5E%5Ccirc%24%20forward%20from%20the%20vertical%20(that%20is%2C%20at%20%2470%5E%5Ccirc%24%20from%20%24X%24)%2C%20and%20its%20%24y%24%20axis%20turned%20%2490%5E%5Ccirc%24%20counterclockwise%20from%20%24x%24.%20Find%20the%20components%20of%20the%20force%20along%20and%20across%20the%20shank.%20Does%20the%20position%20of%20the%20ankle%20enter%20the%20calculation%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_F_G%20%3D%20np.array(%5B120.0%2C%20680.0%5D)%20%20%23%20ground%20reaction%20force%20%5BN%5D%0A%20%20%20%20_R_shank%20%3D%20rotation_2d(np.radians(70))%0A%20%20%20%20_F_l%20%3D%20_R_shank.T%20%40%20_F_G%20%20%23%20Global%20to%20local%3A%20rotation%20only%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%20r%22A%20force%20is%20a%20vector%2C%20not%20a%20position%3A%20it%20has%20a%20magnitude%20and%20a%20direction%2C%20but%20no%20origin%20to%20subtract.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22Only%20the%20rotation%20enters%2C%20%24%5Cmathbf%7BF_l%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5ET%7D%5Cmathbf%7BF_G%7D%24%2C%20and%20the%209%20cm%20of%20the%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22ankle%20play%20no%20role.%20(The%20translation%20cancels%20for%20any%20vector%20that%20is%20a%20difference%20of%20two%20positions%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22and%20velocities%20and%20accelerations%20are%20such%20differences%20divided%20by%20time.)%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22The%20force%20is%20%7B_F_l%5B0%5D%3A.1f%7D%20N%20along%20the%20shank%2C%20compressing%20it%2C%20and%20%7B_F_l%5B1%5D%3A.1f%7D%20N%20across%20it%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22towards%20the%20posterior%20side%20of%20the%20shank%20(the%20local%20%24y%24%20axis%20points%20backward%20and%20up).%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22Its%20magnitude%2C%20%7Bnp.linalg.norm(_F_l)%3A.1f%7D%20N%2C%20is%20the%20same%20in%20both%20coordinate%20systems%2C%20as%20it%20must%20be%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22for%20a%20rotation.%20Almost%20all%20of%20the%20force%20runs%20along%20the%20shank%20because%20the%20force%2C%20at%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22%7Bnp.degrees(np.arctan2(_F_G%5B1%5D%2C%20_F_G%5B0%5D))%3A.1f%7D%C2%B0%20from%20%24X%24%2C%20points%20within%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22%7Bnp.degrees(np.arctan2(_F_G%5B1%5D%2C%20_F_G%5B0%5D))%20-%2070%3A.0f%7D%C2%B0%20of%20the%20shank's%20axis.%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%23%20Transformation%20matrix%0A%0A%20%20%20%20The%20translation%20and%20the%20rotation%20can%20be%20combined%20in%20a%20single%20matrix%2C%20the%20transformation%20matrix%20(also%20called%20the%20homogeneous%20transformation%20matrix)%2C%20by%20adding%20a%20third%20coordinate%20equal%20to%201%20to%20every%20point%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%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Ccos%5Calpha%20%26%20-%5Csin%5Calpha%20%26%20%5Cmathbf%7BL_%7BX%7D%7D%20%5C%5C%0A%20%20%20%20%5Csin%5Calpha%20%26%20%5Chphantom%7B-%7D%5Ccos%5Calpha%20%20%26%20%5Cmathbf%7BL_%7BY%7D%7D%20%5C%5C%0A%20%20%20%200%20%26%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%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%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%20Multiply%20it%20out%20and%20the%20first%20two%20rows%20give%20back%20%24%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%24%2C%20with%20the%20rotation%20applied%20first%2C%20as%20it%20must%20be%3B%20the%20third%20row%20just%20says%20%241%20%3D%201%24.%20These%20are%20the%203%C3%973%20matrices%20in%20the%20figure%20of%20affine%20transformations%20at%20the%20top.%0A%0A%20%20%20%20The%20inverse%20operation%2C%20expressing%20the%20position%20in%20the%20local%20coordinate%20system%20in%20terms%20of%20the%20Global%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%20But%20%24%5Cmathbf%7BT_%7BGl%7D%7D%24%20is%20not%20orthonormal%2C%20so%20its%20inverse%20is%20not%20its%20transpose.%20From%20the%20inverse%20derived%20above%2C%20%24%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5ET%7D%5Cmathbf%7BP_G%7D%20-%20%5Cmathbf%7BR_%7BGl%7D%5ET%7D%5Cmathbf%7BL_G%7D%24%2C%20so%20in%20block%20form%0A%0A%20%20%20%20%24%24%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%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%20%3D%0A%20%20%20%20%5Cunderbrace%7B%5Cbegin%7Bbmatrix%7D%0A%20%20%20%20%5Cmathbf%7BR%5E%7BT%7D_%7BGl%7D%7D%20%26%20-%20%5Cmathbf%7BR%5E%7BT%7D_%7BGl%7D%7D%5Cmathbf%7BL_%7BG%7D%7D%20%5C%5C%0A%20%20%20%200%20%5Cquad%200%20%26%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%7D_%7B%5Cmathbf%7BT_%7BGl%7D%5E%7B-1%7D%7D%7D%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%201%0A%20%20%20%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20where%20the%20top-left%20block%20is%20the%202%C3%972%20transposed%20rotation%20matrix%20and%20the%20top-right%20block%20is%20a%202%C3%971%20column.%20Let's%20write%20both%20as%20functions%20and%20check%20them%20with%20the%20example%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_2d(R%2C%20L)%3A%0A%20%20%20%20%22%22%22Homogeneous%20transformation%20matrix%20T_Gl%20from%20the%20rotation%20matrix%20R_Gl%0A%20%20%20%20(2x2)%20and%20the%20translation%20L_G%20(the%20position%20of%20the%20local%20origin).%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20T%20%3D%20np.eye(3)%0A%20%20%20%20T%5B%3A2%2C%20%3A2%5D%20%3D%20R%0A%20%20%20%20T%5B%3A2%2C%202%5D%20%3D%20np.ravel(L)%0A%20%20%20%20return%20T%0A%0A%0A%40app.function%0Adef%20inverse_transformation_2d(T)%3A%0A%20%20%20%20%22%22%22Inverse%20of%20a%20homogeneous%20transformation%20matrix%2C%20without%20a%20general%0A%20%20%20%20matrix%20inversion%3A%20the%20rotation%20is%20transposed%20and%20the%20translation%20undone.%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20R%20%3D%20T%5B%3A2%2C%20%3A2%5D%0A%20%20%20%20L%20%3D%20T%5B%3A2%2C%202%5D%0A%20%20%20%20T_inv%20%3D%20np.eye(3)%0A%20%20%20%20T_inv%5B%3A2%2C%20%3A2%5D%20%3D%20R.T%0A%20%20%20%20T_inv%5B%3A2%2C%202%5D%20%3D%20-R.T%20%40%20L%0A%20%20%20%20return%20T_inv%0A%0A%0A%40app.cell%0Adef%20_(LGl%2C%20R_basis%2C%20np)%3A%0A%20%20%20%20_T%20%3D%20transformation_2d(R_basis%2C%20LGl)%0A%20%20%20%20_Pl%20%3D%20np.array(%5B1%2C%201%2C%201%5D)%20%20%23%20the%20point%20%5B1%2C%201%5D%20with%20the%20extra%20coordinate%201%0A%20%20%20%20_PG%20%3D%20_T%20%40%20_Pl%0A%20%20%20%20print(%22Transformation%20matrix%20TGl%3A%5Cn%22%2C%20_T)%0A%20%20%20%20print(%22%5CnPG%20%3D%20TGl%20Pl%20%3D%22%2C%20_PG)%0A%0A%20%20%20%20_T_inv%20%3D%20inverse_transformation_2d(_T)%0A%20%20%20%20print(%22%5CnInverse%20from%20the%20formula%3A%5Cn%22%2C%20_T_inv)%0A%20%20%20%20print(%22Same%20as%20np.linalg.inv(TGl)%3F%22%2C%20np.allclose(_T_inv%2C%20np.linalg.inv(_T)))%0A%20%20%20%20print(%22%5CnBack%20to%20local%20coordinates%2C%20T%5E-1%20PG%20%3D%22%2C%20_T_inv%20%40%20_PG)%0A%20%20%20%20print(%22With%20the%20transpose%20instead%2C%20%20%20T%5ET%20PG%20%3D%22%2C%20_T.T%20%40%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%20formula%20agrees%20with%20the%20general%20matrix%20inverse%2C%20and%20takes%20the%20point%20back%20to%20%24%5B1%2C%201%5D%24.%20The%20transpose%2C%20which%20worked%20for%20the%20rotation%20matrix%20alone%2C%20sends%20it%20to%20%24%5B2%2C%200%5D%24%20and%20spoils%20the%20extra%20coordinate%2C%20which%20should%20stay%20equal%20to%201.%0A%0A%20%20%20%20**Exercise%205.**%20A%20local%20coordinate%20system%20is%20rotated%20by%20%2490%5E%5Ccirc%24%20counterclockwise%20and%20has%20its%20origin%20at%20%24%5B2%2C%201%5D%24%20in%20the%20Global%20coordinate%20system.%20Write%20%24%5Cmathbf%7BT_%7BGl%7D%7D%24%2C%20find%20%24%5Cmathbf%7BT_%7BGl%7D%5E%7B-1%7D%7D%24%20with%20the%20block%20formula%20above%20(no%20general%20matrix%20inversion)%2C%20and%20use%20it%20to%20find%20the%20local%20coordinates%20of%20the%20Global%20point%20%24%5B2%2C%203%5D%24.%20Check%20your%20answer%20by%20transforming%20it%20back.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%205%0A%20%20%20%20With%20%24%5Ccos%2090%5E%5Ccirc%20%3D%200%24%20and%20%24%5Csin%2090%5E%5Ccirc%20%3D%201%24%2C%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BT_%7BGl%7D%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%200%20%26%20-1%20%26%202%20%5C%5C%201%20%26%20%5Chphantom%7B-%7D0%20%26%201%20%5C%5C%200%20%26%20%5Chphantom%7B-%7D0%20%26%201%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20For%20the%20inverse%2C%20the%20rotation%20block%20is%20transposed%2C%20and%20the%20translation%20becomes%0A%0A%20%20%20%20%24%24%0A%20%20%20%20-%5Cmathbf%7BR_%7BGl%7D%5ET%7D%5Cmathbf%7BL_G%7D%20%3D%20-%5Cbegin%7Bbmatrix%7D%20%5Chphantom%7B-%7D0%20%26%201%20%5C%5C%20-1%20%26%200%20%5Cend%7Bbmatrix%7D%20%5Cbegin%7Bbmatrix%7D%202%20%5C%5C%201%20%5Cend%7Bbmatrix%7D%20%3D%20-%5Cbegin%7Bbmatrix%7D%20%5Chphantom%7B-%7D1%20%5C%5C%20-2%20%5Cend%7Bbmatrix%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%20-1%20%5C%5C%20%5Chphantom%7B-%7D2%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%5Cquad%20%5CLongrightarrow%20%5Cquad%0A%20%20%20%20%5Cmathbf%7BT_%7BGl%7D%5E%7B-1%7D%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%20%5Chphantom%7B-%7D0%20%26%201%20%26%20-1%20%5C%5C%20-1%20%26%200%20%26%20%5Chphantom%7B-%7D2%20%5C%5C%20%5Chphantom%7B-%7D0%20%26%200%20%26%20%5Chphantom%7B-%7D1%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20Global%20point%20%24%5B2%2C%203%2C%201%5D%24%20goes%20to%20%24%5B0%20%5Ccdot%202%20%2B%201%20%5Ccdot%203%20-%201%2C%5C%3B%20-1%20%5Ccdot%202%20%2B%200%20%5Ccdot%203%20%2B%202%2C%5C%3B%201%5D%20%3D%20%5B2%2C%200%2C%201%5D%24%3A%20the%20local%20point%20%24%5B2%2C%200%5D%24%2C%202%20along%20the%20local%20%24x%24%20axis.%20Back%20again%2C%20%24%5Cmathbf%7BT_%7BGl%7D%7D%5C%2C%5B2%2C%200%2C%201%5D%20%3D%20%5B0%20-%200%20%2B%202%2C%5C%3B%202%20%2B%200%20%2B%201%2C%5C%3B%201%5D%20%3D%20%5B2%2C%203%2C%201%5D%24.%20In%20the%20sketch%2C%20the%20local%20%24x%24%20axis%20points%20along%20the%20Global%20%24Y%24%20axis%20from%20%24%5B2%2C%201%5D%24%2C%20and%202%20along%20it%20is%20%24%5B2%2C%203%5D%24.%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%20Example%3A%20where%20is%20the%20hand%3F%0A%0A%20%20%20%20Transformation%20matrices%20can%20be%20chained%20like%20rotation%20matrices%2C%20and%20this%20is%20where%20they%20earn%20their%20keep.%20Consider%20a%20planar%20model%20of%20the%20arm%2C%20seen%20from%20the%20side.%20The%20upper%20arm%2C%2030%20cm%20long%2C%20is%20turned%20about%20the%20shoulder%20by%20%24%5Ctheta_1%20%3D%2030%5E%5Ccirc%24%20from%20the%20forward%20horizontal%3B%20the%20forearm%2C%2025%20cm%20long%2C%20is%20turned%20about%20the%20elbow%20by%20%24%5Ctheta_2%20%3D%2060%5E%5Ccirc%24%20relative%20to%20the%20upper%20arm.%20Attach%20a%20coordinate%20system%20to%20each%20segment%2C%20with%20its%20origin%20at%20the%20proximal%20joint%20and%20its%20%24x%24%20axis%20along%20the%20segment.%20Then%3A%0A%0A%20%20%20%20-%20the%20upper%20arm's%20coordinate%20system%20(1)%20is%20the%20shoulder's%20(0)%20rotated%20by%20%24%5Ctheta_1%24%2C%20with%20the%20same%20origin%2C%20so%20%24%5Cmathbf%7BT_%7B01%7D%7D%24%20has%20the%20rotation%20%24%5Ctheta_1%24%20and%20the%20translation%20%24%5B0%2C%200%5D%24%3B%0A%20%20%20%20-%20the%20forearm's%20coordinate%20system%20(2)%20is%20the%20upper%20arm's%20rotated%20by%20%24%5Ctheta_2%24%2C%20with%20its%20origin%20at%20the%20elbow%2C%20which%20is%20at%20%24%5B0.30%2C%200%5D%24%20*in%20the%20upper%20arm's%20coordinates*%2C%20so%20%24%5Cmathbf%7BT_%7B12%7D%7D%24%20has%20the%20rotation%20%24%5Ctheta_2%24%20and%20the%20translation%20%24%5B0.30%2C%200%5D%24%3B%0A%20%20%20%20-%20the%20hand%20is%20at%20%24%5B0.25%2C%200%5D%24%20in%20the%20forearm's%20coordinates.%0A%0A%20%20%20%20The%20hand%2C%20in%20the%20shoulder's%20coordinate%20system%2C%20is%20then%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BP_0%7D%20%3D%20%5Cmathbf%7BT_%7B01%7D%7D%5C%2C%5Cmathbf%7BT_%7B12%7D%7D%5C%2C%5Cmathbf%7BP_2%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Each%20matrix%20needs%20only%20what%20is%20simple%20in%20its%20own%20coordinate%20system%3A%20the%20angle%20between%20neighbouring%20segments%20and%20the%20length%20of%20a%20segment.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20where%20the%20hand%20is.%20(Hint%3A%20at%20what%20angle%20from%20the%20horizontal%20does%20the%20forearm%20point%3F)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt)%3A%0A%20%20%20%20_T01%20%3D%20transformation_2d(rotation_2d(np.radians(30))%2C%20%5B0%2C%200%5D)%20%20%23%20upper%20arm%20in%20the%20shoulder's%20system%0A%20%20%20%20_T12%20%3D%20transformation_2d(rotation_2d(np.radians(60))%2C%20%5B0.30%2C%200%5D)%20%20%23%20forearm%20in%20the%20upper%20arm's%20system%0A%20%20%20%20_hand_2%20%3D%20np.array(%5B0.25%2C%200%2C%201%5D)%20%20%23%20hand%20in%20the%20forearm's%20system%2C%20with%20the%20extra%20coordinate%201%0A%0A%20%20%20%20_T02%20%3D%20_T01%20%40%20_T12%0A%20%20%20%20_elbow%20%3D%20_T01%20%40%20%5B0.30%2C%200%2C%201%5D%0A%20%20%20%20_hand%20%3D%20_T02%20%40%20_hand_2%0A%20%20%20%20_hand_wrong%20%3D%20_T12%20%40%20_T01%20%40%20_hand_2%0A%20%20%20%20print(%22Elbow%3A%22%2C%20_elbow%5B%3A2%5D.round(3)%2C%20%22m%3B%20%20hand%3A%22%2C%20_hand%5B%3A2%5D.round(3)%2C%20%22m%22)%0A%20%20%20%20print(%22Check%20with%20trigonometry%3A%22%2C%20np.round(%5B0.30%20*%20np.cos(np.radians(30))%20%2B%200.25%20*%20np.cos(np.radians(90))%2C%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%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%200.30%20*%20np.sin(np.radians(30))%20%2B%200.25%20*%20np.sin(np.radians(90))%5D%2C%203))%0A%20%20%20%20print(%22Hand%20with%20the%20product%20in%20the%20wrong%20order%2C%20T12%20T01%3A%22%2C%20_hand_wrong%5B%3A2%5D.round(3)%2C%20%22m%22)%0A%20%20%20%20print(%22Same%20rotation%20part%20in%20both%20orders%3F%22%2C%20np.allclose(_T02%5B%3A2%2C%20%3A2%5D%2C%20(_T12%20%40%20_T01)%5B%3A2%2C%20%3A2%5D))%0A%0A%20%20%20%20_%2C%20_ax%20%3D%20plt.subplots(figsize%3D(5%2C%205))%0A%20%20%20%20_ax.plot(%5B0%2C%20_elbow%5B0%5D%2C%20_hand%5B0%5D%5D%2C%20%5B0%2C%20_elbow%5B1%5D%2C%20_hand%5B1%5D%5D%2C%20%22o-%22%2C%20color%3D%220.5%22%2C%20linewidth%3D6%2C%20markersize%3D10%2C%20alpha%3D0.6)%0A%20%20%20%20for%20_T%20in%20(np.eye(3)%2C%20_T01%2C%20_T02)%3A%0A%20%20%20%20%20%20%20%20_origin%20%3D%20_T%5B%3A2%2C%202%5D%0A%20%20%20%20%20%20%20%20_ax.quiver(*_origin%2C%20*(0.08%20*%20_T%5B%3A2%2C%200%5D)%2C%20angles%3D%22xy%22%2C%20scale_units%3D%22xy%22%2C%20scale%3D1%2C%20color%3D%22tab%3Ared%22%2C%20width%3D0.008)%0A%20%20%20%20%20%20%20%20_ax.quiver(*_origin%2C%20*(0.08%20*%20_T%5B%3A2%2C%201%5D)%2C%20angles%3D%22xy%22%2C%20scale_units%3D%22xy%22%2C%20scale%3D1%2C%20color%3D%22tab%3Agreen%22%2C%20width%3D0.008)%0A%20%20%20%20_ax.plot(*_hand_wrong%5B%3A2%5D%2C%20%22x%22%2C%20color%3D%22tab%3Apurple%22%2C%20markersize%3D12%2C%20mew%3D3%2C%20label%3D%22hand%20with%20the%20wrong%20order%22)%0A%20%20%20%20_ax.plot(%5B%5D%2C%20%5B%5D%2C%20color%3D%22tab%3Ared%22%2C%20linewidth%3D3%2C%20label%3D%22local%20x%20axes%22)%0A%20%20%20%20_ax.plot(%5B%5D%2C%20%5B%5D%2C%20color%3D%22tab%3Agreen%22%2C%20linewidth%3D3%2C%20label%3D%22local%20y%20axes%22)%0A%20%20%20%20_ax.set_aspect(%22equal%22)%0A%20%20%20%20_ax.margins(0.2)%0A%20%20%20%20_ax.set_xlabel(%22X%20%5Bm%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Y%20%5Bm%5D%22)%0A%20%20%20%20_ax.set_title(%22Shoulder%2C%20elbow%20and%20hand%22)%0A%20%20%20%20_ax.legend(loc%3D%22upper%20left%22%2C%20fontsize%3D10)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%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%20forearm%20points%20straight%20up%2C%20at%20%2430%5E%5Ccirc%20%2B%2060%5E%5Ccirc%20%3D%2090%5E%5Ccirc%24%20from%20the%20horizontal%2C%20so%20the%20hand%20is%2025%20cm%20directly%20above%20the%20elbow%2C%20at%20%24(0.260%2C%200.400)%24%20m%2C%20which%20trigonometry%20confirms.%20The%20figure%20shows%20the%20three%20coordinate%20systems%20we%20used%3A%20two%20at%20the%20shoulder%20(the%20laboratory's%20and%20the%20upper%20arm's)%20and%20one%20at%20the%20elbow%20(the%20forearm's).%0A%0A%20%20%20%20Now%20the%20product%20in%20the%20wrong%20order.%20Its%20rotation%20part%20is%20the%20same%2C%20a%20rotation%20by%20%2490%5E%5Ccirc%24%2C%20because%20in%20a%20plane%20rotations%20commute.%20But%20the%20hand%20lands%20at%20%24(0.300%2C%200.250)%24%20m%2C%2039%20cm%20from%20the%20shoulder%20instead%20of%2048%20cm.%20*Transformation*%20matrices%20do%20not%20commute%2C%20even%20in%20a%20plane%2C%20because%20each%20translation%20is%20written%20in%20the%20coordinate%20system%20of%20the%20segment%20before%20it%3A%20%24%5B0.30%2C%200%5D%24%20means%20%2230%20cm%20along%20the%20upper%20arm%22%20only%20when%20it%20is%20applied%20after%20%24%5Cmathbf%7BT_%7B01%7D%7D%24%20has%20turned%20the%20axes.%20%5BKinematic%20chain%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematic_chain.py)%20builds%20on%20exactly%20this%20product.%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%20Back%20to%20the%20knee%0A%0A%20%20%20%20We%20now%20have%20everything%20needed%20to%20locate%20the%20knee.%20The%20plan%20has%20two%20steps%2C%20one%20in%20each%20direction%3A%0A%0A%20%20%20%201.%20**Calibration%20(Global%20to%20local).**%20In%20the%20standing%20trial%2C%20build%20the%20thigh's%20coordinate%20system%20from%20its%20two%20markers%2C%20and%20express%20the%20knee%20joint%20centre%20in%20it%3A%20%24%5Cmathbf%7BP_l%7D%20%3D%20%5Cmathbf%7BR_%7BGl%7D%5ET%7D(%5Cmathbf%7BP_G%7D%20-%20%5Cmathbf%7BL_G%7D)%24.%20Because%20the%20thigh%20is%20rigid%2C%20these%20local%20coordinates%20never%20change.%0A%20%20%20%202.%20**Reconstruction%20(local%20to%20Global).**%20In%20every%20frame%20of%20the%20movement%2C%20build%20the%20thigh's%20coordinate%20system%20again%20from%20the%20same%20two%20markers%2C%20and%20bring%20the%20knee%20back%20to%20the%20laboratory%3A%20%24%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%24.%0A%0A%20%20%20%20The%20thigh's%20coordinate%20system%20has%20its%20origin%20at%20the%20trochanter%20marker%2C%20its%20%24x%24%20axis%20pointing%20from%20there%20to%20the%20thigh%20marker%2C%20and%20its%20%24y%24%20axis%20turned%20%2490%5E%5Ccirc%24%20counterclockwise%20from%20%24x%24%3A%20exactly%20the%20recipe%20of%20%60segment_rotation_2d%60%2C%20written%20for%20the%20kick%20example%20above.%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%20Calibration%20trial%2C%20standing%20%5Bm%5D%0A%20%20%20%20m1_cal%20%3D%20np.array(%5B0.000%2C%200.900%5D)%20%20%23%20marker%20on%20the%20greater%20trochanter%0A%20%20%20%20m2_cal%20%3D%20np.array(%5B0.020%2C%200.700%5D)%20%20%23%20marker%20on%20the%20lateral%20thigh%0A%20%20%20%20knee_cal%20%3D%20np.array(%5B0.010%2C%200.480%5D)%20%20%23%20knee%20joint%20centre%2C%20located%20in%20this%20trial%20only%0A%0A%20%20%20%20R_cal%20%3D%20segment_rotation_2d(m1_cal%2C%20m2_cal)%0A%20%20%20%20knee_local%20%3D%20R_cal.T%20%40%20(knee_cal%20-%20m1_cal)%20%20%23%20Global%20to%20local%0A%0A%20%20%20%20print(%22Thigh%20angle%20in%20the%20calibration%3A%22%2C%20round(float(np.degrees(np.arctan2(R_cal%5B1%2C%200%5D%2C%20R_cal%5B0%2C%200%5D)))%2C%201)%2C%20%22degrees%22)%0A%20%20%20%20print(%22Knee%20in%20the%20thigh's%20coordinate%20system%3A%22%2C%20knee_local%2C%20%22m%22)%0A%20%20%20%20return%20R_cal%2C%20knee_cal%2C%20knee_local%2C%20m1_cal%2C%20m2_cal%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%20thigh%20points%20almost%20straight%20down%2C%20at%20%24-84.3%5E%5Ccirc%24%20from%20the%20forward%20horizontal%2C%20and%20the%20knee%20is%2041.9%20cm%20along%20the%20thigh's%20%24x%24%20axis%20and%203.2%20cm%20to%20the%20negative%20side%20of%20its%20%24y%24%20axis%3A%20slightly%20behind%20the%20line%20through%20the%20two%20markers%2C%20which%20sit%20on%20the%20side%20of%20the%20thigh%2C%20not%20on%20the%20femur.%0A%0A%20%20%20%20Now%20the%20movement.%20To%20have%20a%20known%20answer%20to%20check%20against%2C%20the%20movement%20markers%20in%20the%20table%20at%20the%20top%20were%20generated%20from%20the%20calibration%3A%20the%20thigh%20was%20turned%20by%20%2460%5E%5Ccirc%24%20counterclockwise%20(hip%20flexion%2C%20with%20%24X%24%20pointing%20forward)%2C%20the%20trochanter%20marker%20was%20moved%20to%20%24(0.150%2C%200.800)%24%2C%20and%20the%20thigh%20marker%20was%20rounded%20to%20the%20millimetre%2C%20as%20a%20motion%20capture%20system%20would%20report%20it.%20The%20same%20transformation%20gives%20the%20true%20position%20of%20the%20knee%2C%20which%20we%20will%20now%20pretend%20not%20to%20know.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(knee_cal%2C%20m1_cal%2C%20m2_cal%2C%20np)%3A%0A%20%20%20%20_R_true%20%3D%20rotation_2d(np.radians(60))%0A%20%20%20%20m1_mov%20%3D%20np.array(%5B0.150%2C%200.800%5D)%0A%20%20%20%20m2_mov%20%3D%20np.round(m1_mov%20%2B%20_R_true%20%40%20(m2_cal%20-%20m1_cal)%2C%203)%20%20%23%20reported%20to%20the%20millimetre%0A%20%20%20%20knee_true%20%3D%20m1_mov%20%2B%20_R_true%20%40%20(knee_cal%20-%20m1_cal)%20%20%23%20the%20answer%20we%20pretend%20not%20to%20know%0A%0A%20%20%20%20print(%22Markers%20in%20the%20movement%20trial%3A%22%2C%20m1_mov%2C%20m2_mov)%0A%20%20%20%20return%20knee_true%2C%20m1_mov%2C%20m2_mov%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%20go%20back%20to%20your%20guess%20in%20Guiding%20question%200.3%2C%20and%20make%20it%20a%20number%3A%20where%20is%20the%20knee%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R_cal%2C%20knee_cal%2C%20knee_local%2C%20knee_true%2C%20m1_cal%2C%20m1_mov%2C%20m2_mov%2C%20np)%3A%0A%20%20%20%20R_mov%20%3D%20segment_rotation_2d(m1_mov%2C%20m2_mov)%0A%20%20%20%20knee_mov%20%3D%20m1_mov%20%2B%20R_mov%20%40%20knee_local%20%20%23%20local%20to%20Global%0A%0A%20%20%20%20_R_rel%20%3D%20R_cal.T%20%40%20R_mov%20%20%23%20rotation%20of%20the%20thigh%20from%20the%20calibration%20to%20the%20movement%0A%20%20%20%20print(%22Thigh%20rotation%20since%20the%20calibration%3A%22%2C%20round(float(np.degrees(np.arctan2(_R_rel%5B1%2C%200%5D%2C%20_R_rel%5B0%2C%200%5D)))%2C%201)%2C%20%22degrees%22)%0A%20%20%20%20print(%22Reconstructed%20knee%3A%22%2C%20knee_mov.round(3)%2C%20%22m%22)%0A%20%20%20%20print(f%22Distance%20from%20the%20true%20knee%3A%20%7B1000%20*%20np.linalg.norm(knee_mov%20-%20knee_true)%3A.1f%7D%20mm%22)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22Knee%20to%20trochanter%20marker%3A%20%7Bnp.linalg.norm(knee_mov%20-%20m1_mov)%3A.3f%7D%20m%22%0A%20%20%20%20%20%20%20%20f%22%20(standing%3A%20%7Bnp.linalg.norm(knee_cal%20-%20m1_cal)%3A.3f%7D%20m)%22%0A%20%20%20%20)%0A%20%20%20%20return%20R_mov%2C%20knee_mov%0A%0A%0A%40app.cell%0Adef%20_(R_cal%2C%20R_mov%2C%20knee_cal%2C%20knee_mov%2C%20m1_cal%2C%20m1_mov%2C%20m2_cal%2C%20m2_mov%2C%20plt)%3A%0A%20%20%20%20_%2C%20_ax%20%3D%20plt.subplots(figsize%3D(7%2C%206))%0A%20%20%20%20for%20_m1%2C%20_m2%2C%20_knee%2C%20_R%2C%20_label%2C%20_color%20in%20%5B%0A%20%20%20%20%20%20%20%20(m1_cal%2C%20m2_cal%2C%20knee_cal%2C%20R_cal%2C%20%22standing%20(calibration)%22%2C%20%220.5%22)%2C%0A%20%20%20%20%20%20%20%20(m1_mov%2C%20m2_mov%2C%20knee_mov%2C%20R_mov%2C%20%22movement%20(reconstructed)%22%2C%20%22tab%3Ablue%22)%2C%0A%20%20%20%20%5D%3A%0A%20%20%20%20%20%20%20%20_ax.plot(%5B_m1%5B0%5D%2C%20_knee%5B0%5D%5D%2C%20%5B_m1%5B1%5D%2C%20_knee%5B1%5D%5D%2C%20color%3D_color%2C%20linewidth%3D8%2C%20alpha%3D0.3%2C%20solid_capstyle%3D%22round%22)%0A%20%20%20%20%20%20%20%20_ax.plot(%5B_m1%5B0%5D%2C%20_m2%5B0%5D%5D%2C%20%5B_m1%5B1%5D%2C%20_m2%5B1%5D%5D%2C%20%22o%22%2C%20color%3D_color%2C%20markersize%3D9)%0A%20%20%20%20%20%20%20%20_ax.plot(*_knee%2C%20%22*%22%2C%20color%3D_color%2C%20markersize%3D20%2C%20label%3Df%22knee%2C%20%7B_label%7D%22)%0A%20%20%20%20%20%20%20%20_ax.quiver(*_m1%2C%20*(0.12%20*%20_R%5B%3A%2C%200%5D)%2C%20angles%3D%22xy%22%2C%20scale_units%3D%22xy%22%2C%20scale%3D1%2C%20color%3D%22tab%3Ared%22%2C%20width%3D0.006)%0A%20%20%20%20%20%20%20%20_ax.quiver(*_m1%2C%20*(0.12%20*%20_R%5B%3A%2C%201%5D)%2C%20angles%3D%22xy%22%2C%20scale_units%3D%22xy%22%2C%20scale%3D1%2C%20color%3D%22tab%3Agreen%22%2C%20width%3D0.006)%0A%20%20%20%20_ax.plot(%5B%5D%2C%20%5B%5D%2C%20color%3D%22tab%3Ared%22%2C%20linewidth%3D3%2C%20label%3Dr%22%24%5Chat%7B%5Cmathbf%7Be%7D%7D_x%24%20of%20the%20thigh%22)%0A%20%20%20%20_ax.plot(%5B%5D%2C%20%5B%5D%2C%20color%3D%22tab%3Agreen%22%2C%20linewidth%3D3%2C%20label%3Dr%22%24%5Chat%7B%5Cmathbf%7Be%7D%7D_y%24%20of%20the%20thigh%22)%0A%20%20%20%20_ax.set_aspect(%22equal%22)%0A%20%20%20%20_ax.margins(0.15)%0A%20%20%20%20_ax.set_xlabel(%22X%20%5Bm%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Y%20%5Bm%5D%22)%0A%20%20%20%20_ax.set_title(%22Thigh%20markers%20(dots)%20and%20knee%20joint%20centre%20(stars)%22)%0A%20%20%20%20_ax.legend(loc%3D%22lower%20right%22%2C%20fontsize%3D10)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%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%20knee%20is%20at%20%24(0.518%2C%200.598)%24%20m%3A%2037%20cm%20in%20front%20of%20the%20trochanter%20marker%20and%2020%20cm%20below%20it%2C%20with%20the%20thigh%20turned%20by%20%2459.9%5E%5Ccirc%24.%20The%20reconstruction%20misses%20the%20true%20position%20by%20less%20than%20a%20millimetre%2C%20and%20that%20small%20miss%20comes%20entirely%20from%20rounding%20the%20thigh%20marker%20to%20the%20millimetre.%20The%20distance%20from%20the%20knee%20to%20the%20trochanter%20marker%20is%20the%20same%2042%20cm%20as%20in%20the%20standing%20trial%2C%20as%20it%20must%20be%20for%20a%20rigid%20transformation.%0A%0A%20%20%20%20Two%20transformations%2C%20one%20in%20each%20direction%2C%20located%20a%20point%20that%20no%20camera%20could%20see.%20This%20is%20how%20the%20anatomical%20coordinate%20systems%20of%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py)%20are%20rebuilt%20in%20every%20frame%20of%20a%20movement%20from%20technical%20markers%2C%20and%20in%20three%20dimensions%20the%20procedure%20is%20the%20same%2C%20with%203%C3%973%20rotation%20matrices.%0A%0A%20%20%20%20**Guiding%20questions%202.**%0A%0A%20%20%20%201.%20The%20thigh's%20coordinate%20system%20had%20its%20origin%20at%20the%20trochanter%20marker.%20If%20the%20origin%20were%20at%20the%20midpoint%20between%20the%20two%20markers%2C%20which%20numbers%20would%20change%3A%20the%20local%20coordinates%20of%20the%20knee%2C%20the%20reconstructed%20knee%2C%20or%20both%3F%0A%20%20%20%202.%20The%20recipe%20used%20only%20two%20markers.%20Why%20is%20that%20enough%20in%20a%20plane%3F%20What%20would%20a%20third%20marker%20add%3F%0A%20%20%20%203.%20The%20rotation%20of%20the%20thigh%20came%20out%20as%20%2459.9%5E%5Ccirc%24%2C%20not%20%2460%5E%5Ccirc%24.%20Where%20did%20the%20missing%20%240.1%5E%5Ccirc%24%20go%3F%0A%0A%20%20%20%20**Exercise%206.**%20In%20another%20frame%20of%20the%20same%20movement%2C%20the%20trochanter%20marker%20is%20at%20%24(0.40%2C%200.85)%24%20m%20and%20the%20thigh%20marker%20at%20%24(0.55%2C%200.72)%24%20m.%20Where%20is%20the%20knee%2C%20and%20how%20much%20has%20the%20thigh%20rotated%20since%20the%20calibration%3F%20Measure%20the%20distance%20between%20the%20two%20markers%20and%20compare%20it%20with%20the%20standing%20trial.%20What%20could%20the%20difference%20mean%2C%20and%20does%20it%20change%20the%20reconstructed%20knee%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(R_cal%2C%20knee_local%2C%20m1_cal%2C%20m2_cal%2C%20mo%2C%20np)%3A%0A%20%20%20%20_m1%2C%20_m2%20%3D%20np.array(%5B0.40%2C%200.85%5D)%2C%20np.array(%5B0.55%2C%200.72%5D)%0A%20%20%20%20_R%20%3D%20segment_rotation_2d(_m1%2C%20_m2)%0A%20%20%20%20_knee%20%3D%20_m1%20%2B%20_R%20%40%20knee_local%20%20%23%20local%20to%20Global%0A%20%20%20%20_R_rel%20%3D%20R_cal.T%20%40%20_R%20%20%23%20rotation%20of%20the%20thigh%20since%20the%20calibration%0A%20%20%20%20_rotation%20%3D%20np.degrees(np.arctan2(_R_rel%5B1%2C%200%5D%2C%20_R_rel%5B0%2C%200%5D))%0A%20%20%20%20_d_now%20%3D%20np.linalg.norm(_m2%20-%20_m1)%0A%20%20%20%20_d_cal%20%3D%20np.linalg.norm(m2_cal%20-%20m1_cal)%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.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Build%20the%20thigh's%20rotation%20matrix%20from%20the%20two%20markers%20of%20this%20frame%20and%20bring%20the%20knee's%20local%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22coordinates%2C%20found%20in%20the%20calibration%2C%20back%20to%20the%20laboratory%3A%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%24%5Cmathbf%7BP_G%7D%20%3D%20%5Cmathbf%7BL_G%7D%20%2B%20%5Cmathbf%7BR_%7BGl%7D%7D%5Cmathbf%7BP_l%7D%24%2C%20with%20%60knee_local%60%20as%20%24%5Cmathbf%7BP_l%7D%24.%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22The%20knee%20is%20at%20(%7B_knee%5B0%5D%3A.3f%7D%2C%20%7B_knee%5B1%5D%3A.3f%7D)%20m%2C%20and%20the%20thigh%20has%20turned%20by%20%7B_rotation%3A.1f%7D%C2%B0%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22since%20the%20calibration.%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22The%20markers%20are%20%7B100%20*%20_d_now%3A.2f%7D%20cm%20apart%2C%20against%20%7B100%20*%20_d_cal%3A.2f%7D%20cm%20standing%3A%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22%7B1000%20*%20(_d_cal%20-%20_d_now)%3A.1f%7D%20mm%20shorter.%20A%20rigid%20thigh%20cannot%20shorten%2C%20so%20the%20markers%20have%20moved%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22on%20the%20skin%2C%20or%20the%20measurement%20is%20off.%20%60segment_rotation_2d%60%20uses%20only%20the%20*direction*%20from%20one%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22marker%20to%20the%20other%2C%20so%20the%20change%20of%20length%20goes%20unnoticed%2C%20and%20the%20knee%20is%20still%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22%7B100%20*%20np.linalg.norm(_knee%20-%20_m1)%3A.1f%7D%20cm%20from%20the%20trochanter%20marker.%20But%20a%20marker%20that%20slides%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22along%20the%20thigh%20may%20also%20slide%20across%20it%2C%20and%20that%20would%20tilt%20the%20axes%20and%20move%20the%20knee%2C%20as%20the%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22simulation%20below%20shows.%20A%20change%20in%20the%20distance%20between%20markers%20is%20a%20warning%20sign%20worth%20checking%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22in%20every%20frame.%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%23%20How%20far%20can%20you%20trust%20the%20reconstructed%20knee%3F%0A%0A%20%20%20%20Real%20markers%20are%20not%20off%20by%20a%20rounding%20error%3B%20they%20are%20off%20by%20a%20millimetre%20or%20so%20in%20every%20frame%2C%20and%20the%20noise%20of%20each%20frame%20is%20different.%20Let's%20add%20random%20noise%20with%20a%20standard%20deviation%20of%201%20mm%20to%20each%20coordinate%20of%20the%20two%20markers%20in%20the%20movement%20trial%2C%20reconstruct%20the%20knee%205000%20times%2C%20and%20measure%20how%20far%20it%20lands%20from%20the%20true%20knee.%20Then%20repeat%20with%20the%20thigh%20marker%20placed%20halfway%2C%2010%20cm%20from%20the%20trochanter%20marker%20instead%20of%2020%20cm.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20with%201%20mm%20of%20noise%20in%20each%20marker%2C%20is%20the%20typical%20error%20of%20the%20knee%20smaller%20than%201%20mm%2C%20about%201%20mm%2C%20or%20larger%3F%20And%20with%20the%20markers%20closer%20together%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(knee_cal%2C%20knee_true%2C%20m1_cal%2C%20m1_mov%2C%20m2_cal%2C%20np)%3A%0A%20%20%20%20_rng%20%3D%20np.random.default_rng(0)%0A%20%20%20%20_n%2C%20_sigma%20%3D%205000%2C%200.001%20%20%23%20number%20of%20simulated%20frames%2C%201%20mm%20of%20noise%0A%20%20%20%20_R_true%20%3D%20rotation_2d(np.radians(60))%0A%0A%20%20%20%20for%20_label%2C%20_fraction%20in%20%5B(%2220%20cm%22%2C%201.0)%2C%20(%2210%20cm%22%2C%200.5)%5D%3A%0A%20%20%20%20%20%20%20%20_m2c%20%3D%20m1_cal%20%2B%20_fraction%20*%20(m2_cal%20-%20m1_cal)%20%20%23%20thigh%20marker%20in%20the%20calibration%0A%20%20%20%20%20%20%20%20_knee_local%20%3D%20segment_rotation_2d(m1_cal%2C%20_m2c).T%20%40%20(knee_cal%20-%20m1_cal)%0A%20%20%20%20%20%20%20%20_m2m%20%3D%20m1_mov%20%2B%20_R_true%20%40%20(_m2c%20-%20m1_cal)%20%20%23%20its%20true%20position%20in%20the%20movement%0A%20%20%20%20%20%20%20%20_m1_noisy%20%3D%20m1_mov%20%2B%20_rng.normal(0%2C%20_sigma%2C%20(_n%2C%202))%0A%20%20%20%20%20%20%20%20_m2_noisy%20%3D%20_m2m%20%2B%20_rng.normal(0%2C%20_sigma%2C%20(_n%2C%202))%0A%20%20%20%20%20%20%20%20_knee%20%3D%20_m1_noisy%20%2B%20segment_rotation_2d(_m1_noisy%2C%20_m2_noisy)%20%40%20_knee_local%0A%20%20%20%20%20%20%20%20_err%20%3D%201000%20*%20np.linalg.norm(_knee%20-%20knee_true%2C%20axis%3D1)%20%20%23%20mm%0A%20%20%20%20%20%20%20%20_err_marker%20%3D%201000%20*%20np.linalg.norm(_m2_noisy%20-%20_m2m%2C%20axis%3D1)%0A%20%20%20%20%20%20%20%20print(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22Markers%20%7B_label%7D%20apart%3A%20knee%20error%20median%20%7Bnp.median(_err)%3A.1f%7D%20mm%2C%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%2095th%20percentile%20%7Bnp.percentile(_err%2C%2095)%3A.1f%7D%20mm%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%20(error%20of%20each%20marker%3A%20median%20%7Bnp.median(_err_marker)%3A.1f%7D%20mm)%22%0A%20%20%20%20%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%20The%20knee%20is%20reconstructed%20worse%20than%20the%20markers%20are%20measured%3A%20a%20typical%20error%20of%202%20mm%20with%20the%20markers%2020%20cm%20apart%2C%20against%201.2%20mm%20for%20each%20marker%2C%20and%20almost%20twice%20that%2C%203.8%20mm%2C%20with%20the%20markers%2010%20cm%20apart.%20With%20the%20closer%20markers%2C%20the%20error%20exceeds%201%20cm%20in%20one%20frame%20in%20twenty.%0A%0A%20%20%20%20Two%20things%20are%20at%20work.%20The%20noise%20tilts%20the%20thigh's%20%24x%24%20axis%20a%20little%2C%20by%20an%20angle%20of%20the%20order%20of%20the%20marker%20error%20divided%20by%20the%20distance%20between%20the%20markers%3B%20halve%20that%20distance%20and%20the%20tilt%20doubles.%20And%20the%20knee%20sits%2042%20cm%20from%20the%20origin%2C%20so%20a%20small%20tilt%20of%20the%20axes%20swings%20it%20through%20an%20arc%20proportional%20to%20that%20lever%20arm.%20A%20point%20reconstructed%20far%20from%20its%20markers%20inherits%20their%20errors%20magnified.%20That%20is%20one%20more%20reason%20to%20spread%20the%20markers%20of%20a%20segment%20well%20apart%2C%20as%20%5BDetermination%20of%20a%20coordinate%20system%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fcoordinate_system.py)%20found%20for%20the%20axes%20themselves.%0A%0A%20%20%20%20**Challenge%202.**%20Move%20the%20origin%20of%20the%20thigh's%20coordinate%20system%20to%20the%20midpoint%20of%20the%20two%20markers%20(Guiding%20question%202.1)%2C%20and%20repeat%20the%20simulation.%20Does%20the%20error%20of%20the%20knee%20change%3F%20Explain%20why%2C%20in%20terms%20of%20the%20lever%20arm.%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%20Checkpoint%20questions%0A%0A%20%20%20%20Pause%20here%20before%20the%20problems.%0A%0A%20%20%20%201.%20Go%20back%20to%20the%20coin%20of%20Challenge%200.%20When%20you%20turned%20the%20paper%2C%20which%20coordinates%20of%20the%20coin%20changed%2C%20those%20on%20the%20paper's%20axes%20or%20those%20on%20the%20table's%3F%20Which%20rotation%20matrix%2C%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20or%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%2C%20converts%20the%20paper's%20coordinates%20into%20the%20table's%3F%0A%20%20%20%202.%20A%20camera%20measures%20a%20marker%20in%20the%20laboratory%2C%20and%20you%20want%20its%20coordinates%20in%20the%20segment's%20coordinate%20system.%20Do%20you%20multiply%20by%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20or%20by%20its%20transpose%3F%20Do%20you%20subtract%20the%20translation%20before%20or%20after%3F%0A%20%20%20%203.%20Why%20is%20the%20inverse%20of%20a%20rotation%20matrix%20its%20transpose%2C%20while%20the%20inverse%20of%20a%20transformation%20matrix%20is%20not%3F%0A%20%20%20%204.%20The%20columns%20of%20%24%5Cmathbf%7BR_%7BGl%7D%7D%24%20are%20the%20local%20versors%20in%20Global%20coordinates.%20What%20are%20its%20rows%3F%0A%20%20%20%205.%20Two%20rotations%20in%20a%20plane%20give%20the%20same%20result%20in%20either%20order.%20Give%20a%20physical%20reason%20why%20that%20cannot%20be%20true%20in%20three%20dimensions.%0A%20%20%20%206.%20The%20reconstructed%20knee%20was%20about%20twice%20as%20uncertain%20as%20each%20marker.%20Name%20two%20choices%20in%20the%20design%20of%20an%20experiment%20that%20would%20reduce%20that%20error.%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.%20A%20local%20coordinate%20system%20is%20rotated%2030%C2%B0%20clockwise%20in%20relation%20to%20the%20Global%20reference%20system.%3Cbr%3E%0A%20%20%20%20%20%20%20A.%20Determine%20the%20matrices%20for%20rotating%20one%20coordinate%20system%20to%20the%20other%20(two-dimensional).%3Cbr%3E%0A%20%20%20%20%20%20%20B.%20What%20are%20the%20coordinates%20of%20the%20point%20%5B1%2C%201%5D%20(local%20coordinate%20system)%20in%20the%20Global%20coordinate%20system%3F%3Cbr%3E%0A%20%20%20%20%20%20%20C.%20And%20if%20this%20point%20is%20in%20the%20Global%20coordinate%20system%20and%20we%20want%20its%20coordinates%20in%20the%20local%20coordinate%20system%3F%3Cbr%3E%0A%20%20%20%20%20%20%20D.%20Consider%20that%20the%20local%20coordinate%20system%2C%20besides%20the%20rotation%2C%20is%20also%20translated%20by%20%5B2%2C%202%5D.%20What%20are%20the%20matrices%20for%20rotation%2C%20translation%2C%20and%20transformation%20from%20one%20coordinate%20system%20to%20the%20other%20(two-dimensional)%3F%3Cbr%3E%0A%20%20%20%20%20%20%20E.%20Repeat%20B%20and%20C%20considering%20this%20translation.%0A%0A%20%20%20%202.%20Consider%20a%20local%20coordinate%20system%20U%20rotated%2045%C2%B0%20clockwise%20in%20relation%20to%20the%20Global%20reference%20system%2C%20and%20another%20local%20coordinate%20system%20V%20rotated%2045%C2%B0%20clockwise%20in%20relation%20to%20the%20local%20reference%20system%20U.%3Cbr%3E%0A%20%20%20%20%20%20%20A.%20Determine%20the%20rotation%20matrices%20of%20all%20possible%20transformations%20between%20the%20coordinate%20systems.%3Cbr%3E%0A%20%20%20%20%20%20%20B.%20For%20the%20point%20%5B1%2C%201%5D%20in%20the%20coordinate%20system%20U%2C%20what%20are%20its%20coordinates%20in%20the%20coordinate%20system%20V%20and%20in%20the%20Global%20coordinate%20system%3F%0A%0A%20%20%20%203.%20Using%20the%20rotation%20matrix%2C%20deduce%20the%20new%20coordinates%20of%20a%20square%20with%20vertices%20%5B0%2C%200%5D%2C%20%5B1%2C%200%5D%2C%20%5B1%2C%201%5D%20and%20%5B0%2C%201%5D%20when%20rotated%20by%200%C2%B0%2C%2045%C2%B0%2C%2090%C2%B0%2C%20135%C2%B0%20and%20180%C2%B0%20(always%20clockwise).%0A%0A%20%20%20%204.%20Solve%20problem%202%20of%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)%2C%20but%20now%20using%20the%20concept%20of%20two-dimensional%20transformations.%0A%0A%20%20%20%205.%20Rotate%20an%20%24n%5Ctimes%20n%24%20image%20matrix%2090%C2%B0%20clockwise%20in%20place%2C%20as%20in%20%5BRotate%20Image%5D(https%3A%2F%2Fleetcode.com%2Fproblems%2Frotate-image%2F).%20Give%20a%20constant-extra-space%20implementation%3B%20distinguish%20it%20from%20a%20concise%20implementation%20that%20allocates%20a%20copy.%0A%0A%20%20%20%206.%20Rotate%20a%20triangle%20with%20vertices%20A(0%2C%200)%2C%20B(1%2C%201)%20and%20C(5%2C%202)%20by%20an%20angle%20of%2045%C2%B0%20with%20respect%20to%20the%20origin.%20(From%20a%20%5Bnumerical%20example%20at%20studyresearch.in%5D(https%3A%2F%2Fweb.archive.org%2Fweb%2F20250223024131%2Fhttps%3A%2F%2Fstudyresearch.in%2F2019%2F12%2F14%2Fnumerical-example-of-rotation-in-2d-transformation%2F)%2C%20archived%20copy.)%0A%0A%20%20%20%207.%20Rotate%20a%20triangle%20with%20vertices%20A(0%2C%200)%2C%20B(1%2C%201)%20and%20C(5%2C%202)%20by%20an%20angle%20of%2045%C2%B0%20with%20respect%20to%20the%20point%20P(%E2%88%921%2C%20%E2%88%921).%20(From%20the%20same%20%5Bnumerical%20example%5D(https%3A%2F%2Fweb.archive.org%2Fweb%2F20250223024131%2Fhttps%3A%2F%2Fstudyresearch.in%2F2019%2F12%2F14%2Fnumerical-example-of-rotation-in-2d-transformation%2F).)%0A%0A%20%20%20%208.%20In%20the%20knee%20example%2C%20define%20the%20thigh's%20coordinate%20system%20with%20its%20origin%20at%20the%20midpoint%20between%20the%20two%20markers%2C%20keeping%20the%20same%20axes.%20Calculate%20the%20local%20coordinates%20of%20the%20knee%20in%20the%20calibration%20and%20the%20reconstructed%20knee%20in%20the%20movement.%20Which%20numbers%20change%2C%20and%20which%20do%20not%3F%0A%0A%20%20%20%209.%20Show%20that%2C%20if%20the%20axes%20of%20a%20segment's%20coordinate%20system%20are%20tilted%20by%20a%20small%20angle%20%24%5Cdelta%5Ctheta%24%20(in%20radians)%2C%20a%20point%20reconstructed%20at%20a%20distance%20%24d%24%20from%20the%20origin%20moves%20by%20about%20%24d%5C%2C%5Cdelta%5Ctheta%24.%20Use%20this%20to%20estimate%2C%20without%20simulation%2C%20how%20the%20error%20of%20the%20reconstructed%20knee%20changes%20when%20the%20distance%20between%20the%20two%20thigh%20markers%20is%20halved%2C%20and%20compare%20with%20the%20simulation%20in%20this%20notebook.%0A%0A%20%20%20%2010.%20In%20the%20centre-of-pressure%20example%2C%20the%20same%20person%20walks%20again%20with%20the%20foot%20turned%20out%20further%3A%20the%20heel%20marker%20is%20at%20(0.500%2C%200.100)%20m%20and%20the%20toe%20marker%20at%20(0.729%2C%200.183)%20m.%20The%20COP%20at%20the%20same%20three%20instants%20is%20(0.512%2C%200.098)%2C%20(0.605%2C%200.130)%20and%20(0.718%2C%200.190)%20m.%3Cbr%3E%0A%20%20%20%20%20%20%20%20a.%20Calculate%20the%20angle%20of%20the%20foot%20and%20the%20COP%20in%20the%20foot's%20coordinate%20system.%3Cbr%3E%0A%20%20%20%20%20%20%20%20b.%20Compare%20with%20the%20example.%20Which%20description%2C%20in%20the%20laboratory%20or%20in%20the%20foot%2C%20would%20you%20use%20to%20compare%20the%20two%20trials%2C%20and%20why%3F%0A%0A%20%20%20%2011.%20A%20planar%20model%20of%20the%20leg%2C%20seen%20from%20the%20side%2C%20has%20a%20thigh%20of%200.42%20m%2C%20a%20shank%20of%200.40%20m%20and%20a%20foot%20of%200.20%20m%20from%20the%20ankle%20to%20the%20toes.%20At%20one%20instant%2C%20the%20thigh%20is%20at%20%24-70%5E%5Ccirc%24%20from%20the%20forward%20horizontal%2C%20the%20shank%20is%20turned%20by%20%24-40%5E%5Ccirc%24%20relative%20to%20the%20thigh%2C%20and%20the%20foot%20by%20%24%2B100%5E%5Ccirc%24%20relative%20to%20the%20shank.%3Cbr%3E%0A%20%20%20%20%20%20%20%20a.%20With%20one%20transformation%20matrix%20per%20segment%2C%20as%20in%20the%20example%20of%20the%20arm%2C%20find%20the%20positions%20of%20the%20knee%2C%20the%20ankle%20and%20the%20toes%20relative%20to%20the%20hip%2C%20and%20check%20them%20with%20trigonometry.%3Cbr%3E%0A%20%20%20%20%20%20%20%20b.%20Use%20the%20inverse%20of%20the%20product%20of%20the%20matrices%20to%20find%20the%20position%20of%20the%20hip%20in%20the%20foot's%20coordinate%20system.%0A%0A%20%20%20%2012.%20Gait%20data%20of%20the%20two%20sides%20are%20often%20plotted%20together%20by%20mirroring%20one%20side%2C%20flipping%20the%20sign%20of%20%24X%24.%20Mirror%20the%20thigh%20markers%20of%20the%20knee%20example%2C%20calculate%20the%20thigh's%20angle%20with%20%60segment_rotation_2d%60%2C%20and%20compare%20it%20with%20the%20original%20%24-84.3%5E%5Ccirc%24.%3Cbr%3E%0A%20%20%20%20%20%20%20%20a.%20Show%20that%20mirroring%20turns%20a%20segment%20angle%20%24%5Ctheta%24%20into%20%24180%5E%5Ccirc%20-%20%5Ctheta%24%2C%20and%20that%20it%20changes%20the%20sign%20of%20the%20angle%20between%20two%20segments.%3Cbr%3E%0A%20%20%20%20%20%20%20%20b.%20Propose%20how%20to%20report%20joint%20angles%20so%20that%20the%20mirrored%20and%20the%20original%20side%20can%20be%20compared%20directly.%0A%0A%20%20%20%2013.%20Repeat%20the%20simulation%20of%20the%20kick%20example%2C%20and%20reconstruct%20in%20every%20frame%20the%20position%20of%20a%20point%20of%20the%20foot%2C%20treated%20as%20rigidly%20attached%20to%20the%20shank%2C%20at%20the%20local%20coordinates%20%24%5B0.45%2C%200.10%5D%24%20m%20in%20the%20shank's%20coordinate%20system%20(origin%20at%20the%20knee).%20Plot%20its%20path%20in%20the%20laboratory%20and%20find%20the%20frame%20in%20which%20it%20is%20highest.%20Use%20arrays%20of%20matrices%2C%20without%20a%20loop%20over%20the%20frames.%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.%20Let%20%24c%3D%5Csqrt3%2F2%24%2C%20%24s%3D1%2F2%24.%20Local-to-global%20%24R%3D%5B%5Bc%2Cs%5D%2C%5B-s%2Cc%5D%5D%24%3B%20global-to-local%20%24R%5ET%24.%20(B)%20%24(1.366025%2C0.366025)%24.%20(C)%20%24(0.366025%2C1.366025)%24.%20With%20translation%20%24L%3D(2%2C2)%24%2C%20%24T_%7BGl%7D%3D%5B%5Bc%2Cs%2C2%5D%2C%5B-s%2Cc%2C2%5D%2C%5B0%2C0%2C1%5D%5D%24%2C%20%24T_%7BlG%7D%3D%5B%5Bc%2C-s%2C-2c%2B2s%5D%2C%5Bs%2Cc%2C-2s-2c%5D%2C%5B0%2C0%2C1%5D%5D%24.%20(E)%20%24(3.366025%2C2.366025)%24%20and%20%24(-0.366025%2C-1.366025)%24%2C%20respectively.%20The%20separate%20translation%20matrix%20is%20%24%5B%5B1%2C0%2C2%5D%2C%5B0%2C1%2C2%5D%2C%5B0%2C0%2C1%5D%5D%24.%0A%20%20%20%202.%20With%20%24Q%3DR(-45%5E%5Ccirc)%24%3A%20%24R_%7BGU%7D%3DR_%7BUV%7D%3DQ%24%2C%20%24R_%7BGV%7D%3DQ%5E2%3DR(-90%5E%5Ccirc)%24%3B%20reverse%20maps%20are%20their%20transposes.%20The%20point%20is%20%24(0%2C%5Csqrt2)%24%20in%20V%20and%20%24(%5Csqrt2%2C0)%24%20in%20G.%0A%20%20%20%203.%20For%20each%20clockwise%20angle%20%24%5Cphi%5Cin%5C%7B0%2C45%2C90%2C135%2C180%5C%7D%5E%5Ccirc%24%2C%20the%20ordered%20vertices%20are%20%24(0%2C0)%24%2C%20%24(%5Ccos%5Cphi%2C-%5Csin%5Cphi)%24%2C%20%24(%5Ccos%5Cphi%2B%5Csin%5Cphi%2C%5Ccos%5Cphi-%5Csin%5Cphi)%24%2C%20%24(%5Csin%5Cphi%2C%5Ccos%5Cphi)%24.%20This%20gives%20all%20five%20requested%20squares%20without%20changing%20vertex%20order.%0A%20%20%20%204.%20The%20final%20segment%20orientations%20and%20joint-angle%20curves%20are%20the%20same%20as%20in%20KinematicsAngular2D%20when%20conventions%20match.%20The%20joint%20matrix%20is%20%24R_1%5ETR_2%24%3B%20its%20signed%20angle%20is%20%60atan2(R_joint%5B1%2C0%5D%2C%20R_joint%5B0%2C0%5D)%60%2C%20with%20anatomical%20offsets%20applied%20consistently.%0A%20%20%20%205.%20A%20constant-extra-space%20final%20implementation%20is%3A%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20n%20%3D%20len(matrix)%0A%20%20%20%20for%20layer%20in%20range(n%20%2F%2F%202)%3A%0A%20%20%20%20%20%20%20%20last%20%3D%20n%20-%201%20-%20layer%0A%20%20%20%20%20%20%20%20for%20j%20in%20range(layer%2C%20last)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20offset%20%3D%20j%20-%20layer%0A%20%20%20%20%20%20%20%20%20%20%20%20saved%20%3D%20matrix%5Blayer%5D%5Bj%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20matrix%5Blayer%5D%5Bj%5D%20%3D%20matrix%5Blast-offset%5D%5Blayer%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20matrix%5Blast-offset%5D%5Blayer%5D%20%3D%20matrix%5Blast%5D%5Blast-offset%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20matrix%5Blast%5D%5Blast-offset%5D%20%3D%20matrix%5Bj%5D%5Blast%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20matrix%5Bj%5D%5Blast%5D%20%3D%20saved%0A%20%20%20%20%60%60%60%0A%20%20%20%206.%20For%20positive%20counterclockwise%2045%C2%B0%3A%20%24A'%3D(0%2C0)%24%2C%20%24B'%3D(0%2C%5Csqrt2)%24%2C%20%24C'%3D(3%2F%5Csqrt2%2C7%2F%5Csqrt2)%24.%0A%20%20%20%207.%20%24A'%3D(-1%2C%5Csqrt2-1)%24%2C%20%24B'%3D(-1%2C2%5Csqrt2-1)%24%2C%20%24C'%3D(3%2F%5Csqrt2-1%2C9%2F%5Csqrt2-1)%24.%0A%20%20%20%208.%20Midpoint-origin%20knee%20coordinates%20in%20calibration%20%24(0.318412%2C-0.031841)%24%20m.%20Reconstructed%20laboratory%20knee%20remains%20%24(0.518353%2C0.597970)%24%20m%3B%20changing%20the%20frame%20origin%20changes%20coordinates%2C%20not%20the%20physical%20point.%20Millimetre-rounded%20movement%20markers%20introduce%20a%20small%20apparent%20change%20in%20inter-marker%20length%2C%20so%20retain%20the%20calibrated%20origin%20offset%20when%20changing%20origins.%0A%20%20%20%209.%20Exact%20displacement%20magnitude%20%242d%7C%5Csin(%5Cdelta%5Ctheta%2F2)%7C%24%2C%20approximately%20%24d%7C%5Cdelta%5Ctheta%7C%24.%20Halving%20marker%20separation%20approximately%20doubles%20the%20angular%20contribution%20to%20landmark%20error%3B%20it%20does%20not%20necessarily%20double%20independent%20translational%20error.%0A%20%20%20%2010.%20Foot%20angle%2019.9228%C2%B0.%20Local%20COP%20positions%20are%20%24(0.010600%2C-0.005969)%24%2C%20%24(0.108939%2C-0.007575)%24%20and%20%24(0.235621%2C0.010329)%24%20m.%20The%20foot%20frame%20removes%20the%20trial%E2%80%99s%20different%20foot%20orientation%20and%20makes%20progression%20and%20medial%2Flateral%20offsets%20comparable.%0A%20%20%20%2011.%20Knee%20%24(0.143648%2C-0.394671)%24%20m%2C%20ankle%20%24(0.006840%2C-0.770548)%24%20m%2C%20toes%20%24(0.203802%2C-0.805278)%24%20m%2C%20relative%20to%20hip.%20Hip%20coordinates%20in%20the%20foot%20frame%20are%20%24(-0.140541%2C0.757654)%24%20m%20if%20its%20origin%20is%20the%20ankle%2C%20or%20%24(-0.340541%2C0.757654)%24%20m%20if%20the%20product%E2%80%99s%20endpoint%20origin%20is%20at%20the%20toes.%20State%20which%20convention%20the%20matrices%20use.%0A%20%20%20%2012.%20The%20mirrored%20segment%20angle%20is%20approximately%20%E2%88%9295.7%C2%B0%20on%20the%20principal%20branch%2C%20equivalent%20to%20%24180%5E%5Ccirc-(-84.3%5E%5Ccirc)%24%20modulo%20360%C2%B0.%20Relative%20signed%20angles%20reverse%3B%20apply%20a%20declared%20side-dependent%20sign%20so%20flexion%20has%20the%20same%20reported%20sign%20on%20both%20sides.%0A%20%20%20%2013.%20Highest%20point%20at%20zero-based%20frame%2050%20(0.5%20s)%2C%20laboratory%20coordinates%20approximately%20%24(-0.341396%2C0.593859)%24%20m.%20The%20path%20is%20symmetric%20in%20time%20about%20this%20peak%20for%20the%20supplied%20sinusoidal%20kick.%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(hide_code%3DTrue)%0Adef%20_(mo%2C%20np%2C%20plt)%3A%0A%20%20%20%20_t%20%3D%20np.linspace(0%2C1%2C101)%0A%20%20%20%20_thigh%20%3D%20np.radians(-90%2B15*np.sin(np.pi*_t))%0A%20%20%20%20_shank%20%3D%20_thigh-np.radians(130*np.sin(np.pi*_t))%0A%20%20%20%20_knee%20%3D%20np.c_%5Bnp.zeros_like(_t)%2C%20np.full_like(_t%2C0.9)%5D%2B0.42*np.c_%5Bnp.cos(_thigh)%2Cnp.sin(_thigh)%5D%0A%20%20%20%20_point%20%3D%20_knee%2B0.45*np.c_%5Bnp.cos(_shank)%2Cnp.sin(_shank)%5D%2B0.10*np.c_%5B-np.sin(_shank)%2Cnp.cos(_shank)%5D%0A%20%20%20%20_fig%2C_ax%3Dplt.subplots(figsize%3D(6%2C4))%0A%20%20%20%20_ax.plot(_point%5B%3A%2C0%5D%2C_point%5B%3A%2C1%5D)%0A%20%20%20%20_i%3Dnp.argmax(_point%5B%3A%2C1%5D)%0A%20%20%20%20_ax.plot(*_point%5B_i%5D%2C%22o%22)%0A%20%20%20%20_ax.set(xlabel%3D%22Laboratory%20X%20%5Bm%5D%22%2Cylabel%3D%22Laboratory%20Y%20%5Bm%5D%22%2Caspect%3D%22equal%22%2Ctitle%3D%22Final%20foot-point%20path%20%E2%80%94%20Problem%2013%22)%0A%20%20%20%20_problem_plot%20%3D%20mo.accordion(%7B%22Final%20path%20%E2%80%94%20Problem%2013%22%3A%20mo.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%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)%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%20751%E2%80%93758%20of%20chapter%2016%20of%20%5BRuina%20and%20Pratap's%20book%5D(https%3A%2F%2Fruina.tam.cornell.edu%2FBook%2Findex.html)%20about%20the%20rotation%20matrix.%0A%20%20%20%20-%20Read%20section%202.8%20of%20Rade's%20book%20about%20the%20rotation%20matrix%20applied%20to%20kinematic%20chains.%0A%20%20%20%20-%20%5BRotation%20matrix%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FRotation_matrix)%20-%20Wikipedia.%0A%20%20%20%20-%20%5BRigid-body%20transformations%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_3d.py)%3A%20the%20same%20ideas%20in%20three%20dimensions%2C%20where%20rotations%20no%20longer%20commute.%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%20bases%20used%20here%20are%20built%20from%20markers%2C%20and%20how%20marker%20errors%20propagate%20to%20them.%0A%20%20%20%20-%20%5BKinematic%20chain%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematic_chain.py)%3A%20products%20of%20transformations%20along%20a%20chain%20of%20links.%0A%0A%20%20%20%20%23%23%23%20Video%20lectures%20on%20the%20Internet%0A%0A%20%20%20%20-%20%5BLinear%20transformation%20examples%3A%20Rotations%20in%20R2%5D(https%3A%2F%2Fwww.khanacademy.org%2Fmath%2Flinear-algebra%2Fmatrix-transformations%2Flin-trans-examples%2Fv%2Flinear-transformation-examples-rotations-in-r2)%20-%20Khan%20Academy%0A%20%20%20%20-%20%5BLinear%20transformations%20and%20matrices%20%7C%20Chapter%203%2C%20Essence%20of%20linear%20algebra%5D(https%3A%2F%2Fyoutu.be%2FkYB8IZa5AuE)%20-%203Blue1Brown%0A%20%20%20%20-%20%5BLinear%20Transformations%20and%20Their%20Matrices%5D(https%3A%2F%2Fyoutu.be%2FTs3o2I8_Mxc)%20-%20MIT%20OpenCourseWare%0A%20%20%20%20-%20%5BRotation%20Matrices%5D(https%3A%2F%2Fyoutu.be%2F4srS0s1d9Yw)%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-%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-%20Winter%20DA%20(2009)%20%5BBiomechanics%20and%20Motor%20Control%20of%20Human%20Movement%5D(https%3A%2F%2Fbooks.google.com.br%2Fbooks%3Fid%3D_bFHL08IWfwC).%204th%20edition.%20Hoboken%2C%20USA%3A%20Wiley.%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%3A%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
737af43ad54d32c26ddc8f9d40844a3a