%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%22scipy%3E%3D1.14%22%2C%20%22sympy%3E%3D1.13%22%2C%20%22pandas%3E%3D2.2%22%2C%20%22urllib3%3E%3D2.2%22%5D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.25.2%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Angular%20velocity%20in%203D%20movements%0A%0A%20%20%20%20%3E%20Renato%20Naville%20Watanabe%2C%20Marcos%20Duarte%3Cbr%3E%0A%20%20%20%20%3E%20%5BLaboratory%20of%20Biomechanics%20and%20Motor%20Control%5D(https%3A%2F%2Fbmclab.pesquisa.ufabc.edu.br%2F)%3Cbr%3E%0A%20%20%20%20%3E%20Federal%20University%20of%20ABC%2C%20Brazil%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20How%20to%20use%20this%20guide%0A%0A%20%20%20%20In%20a%20plane%2C%20angular%20velocity%20is%20easy%3A%20one%20angle%2C%20one%20derivative%2C%20one%20number%20with%20a%20sign.%20In%20three%20dimensions%20a%20body%20segment%20can%20flex%2C%20tilt%20and%20twist%20at%20the%20same%20time%2C%20and%20the%20familiar%20recipe%20of%20differentiating%20an%20angle%20stops%20working.%20Three%20angles%20describe%20the%20orientation%2C%20but%20their%20three%20derivatives%20are%20*not*%20the%20angular%20velocity.%0A%0A%20%20%20%20This%20notebook%20finds%20the%20angular%20velocity%20of%20a%20body%20in%203D%20from%20what%20a%20motion%20capture%20system%20actually%20gives%20you%3A%20a%20basis%20attached%20to%20the%20body%2C%20frame%20after%20frame.%20It%20starts%20with%20the%20axis%20about%20which%20a%20body%20has%20turned%2C%20shows%20why%20finite%20rotations%20cannot%20be%20added%20like%20vectors%20while%20angular%20velocities%20can%2C%20derives%20a%20formula%20that%20needs%20nothing%20but%20dot%20products%2C%20checks%20it%20on%20motions%20with%20known%20answers%2C%20and%20applies%20it%20to%20a%20forearm%2C%20a%20pendulum%20and%20the%20shank%20of%20a%20person%20walking.%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%20number%20*before*%20the%20code%20prints%20it.%20Make%20the%20prediction%3B%20a%20wrong%20guess%20that%20the%20code%20then%20corrects%20teaches%20more%20than%20a%20right%20one.%20The%20**Exercises**%20come%20with%20collapsed%20solutions%3A%20open%20one%20only%20after%20you%20have%20tried%20the%20exercise%20yourself.%0A%0A%20%20%20%20You%20will%20need%20the%20planar%20angular%20velocity%20and%20%24%5Cvec%7B%5Cmathbf%7Bv%7D%7D%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20%5Cvec%7B%5Cmathbf%7Br%7D%7D%24%20from%20%5BKinematics%20of%20a%20rigid%20body%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_of_rigid_body.py)%2C%20rotation%20matrices%20and%20Cardan%20angles%20from%20%5BRigid-body%20transformations%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_3d.py)%2C%20and%20a%20basis%20attached%20to%20a%20segment%2C%20built%20from%20markers%20as%20in%20%5BFrame%20of%20reference%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Freference_frame.py).%0A%0A%20%20%20%20**Challenge%200.**%20Before%20you%20begin%2C%20pick%20up%20a%20pen.%20Spin%20it%20about%20its%20long%20axis%20with%20your%20fingers%20while%20you%20swing%20your%20arm%20in%20an%20arc.%20At%20any%20one%20instant%2C%20is%20there%20a%20single%20line%20about%20which%20the%20pen%20is%20rotating%3F%20Or%20two%20rotations%20going%20on%20at%20once%3F%20Write%20down%20your%20answer%3B%20the%20checkpoint%20questions%20ask%20you%20to%20come%20back%20to%20it.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20How%20fast%20is%20the%20shank%20turning%3F%0A%0A%20%20%20%20In%20%5BRigid-body%20transformations%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_3d.py)%2C%20the%20orientation%20of%20the%20right%20shank%20during%20a%20stride%20was%20described%20by%20three%20Cardan%20angles.%20The%20largest%20of%20them%2C%20%24%5Cgamma%24%2C%20the%20inclination%20of%20the%20shank%20in%20the%20sagittal%20plane%2C%20goes%20from%20about%20%24-65%5E%5Ccirc%24%20to%20%24%2B36%5E%5Ccirc%24%20during%20the%20stride%2C%20and%20in%20late%20swing%20it%20changes%20at%20almost%20%24380%5E%5Ccirc%24%2Fs.%20The%20other%20two%20angles%20change%20too%2C%20by%20tens%20of%20degrees%2C%20while%20the%20shank%20swings.%0A%0A%20%20%20%20So%20how%20fast%20is%20the%20shank%20turning%3F%20Is%20it%20%24380%5E%5Ccirc%24%2Fs%3F%20Is%20the%20angular%20velocity%20a%20vector%20with%20the%20three%20angle%20rates%20as%20its%20components%3F%0A%0A%20%20%20%20**Guiding%20questions%200.**%0A%0A%20%20%20%201.%20In%20a%20plane%2C%20the%20angular%20velocity%20is%20the%20derivative%20of%20the%20angle.%20Why%20might%20that%20stop%20being%20true%20when%20there%20are%20three%20angles%3F%0A%20%20%20%202.%20The%20same%20orientations%20described%20with%20another%20Cardan%20sequence%20give%20different%20angles%2C%20and%20so%20different%20angle%20rates.%20Should%20two%20people%20using%20different%20sequences%20get%20different%20angular%20velocities%20for%20the%20same%20shank%3F%0A%20%20%20%203.%20The%20angular%20velocity%20is%20a%20vector.%20What%20would%20its%20direction%20mean%20physically%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Python%20setup%0A%0A%20%20%20%20NumPy%20does%20the%20numerical%20work%2C%20Matplotlib%20draws%20the%20figures%20and%20SymPy%20derives%20a%20formula%20symbolically.%20The%20functions%20%60CCSbasis%60%20and%20%60read_trc%60%2C%20from%20the%20%60functions%60%20folder%20of%20this%20repository%2C%20draw%20coordinate%20systems%20and%20read%20motion%20capture%20files%3B%20they%20are%20loaded%20where%20they%20are%20first%20needed.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20sympy%20as%20sym%0A%0A%20%20%20%20matplotlib.rc(%22axes%22%2C%20labelsize%3D13%2C%20titlesize%3D14)%0A%20%20%20%20matplotlib.rc(%22xtick%22%2C%20labelsize%3D11)%0A%20%20%20%20matplotlib.rc(%22ytick%22%2C%20labelsize%3D11)%0A%20%20%20%20matplotlib.rc(%22legend%22%2C%20fontsize%3D11)%0A%20%20%20%20return%20np%2C%20plt%2C%20sym%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20A%20basis%20attached%20to%20the%20body%0A%0A%20%20%20%20A%20usual%20problem%20in%20biomechanics%2C%20and%20in%20mechanics%20in%20general%2C%20is%20to%20find%20the%20angular%20velocity%20of%20an%20object.%20We%20consider%20that%20a%20basis%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%2C%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_2%24%20and%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24%20is%20attached%20to%20the%20body%20and%20is%20known%20at%20every%20instant.%20To%20learn%20how%20to%20find%20such%20a%20basis%20from%20the%20positions%20of%20markers%2C%20see%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).%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-1%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2F3DbodyrefMove.png%3Fraw%3D1%22%20width%3D600%20alt%3D%22a%20body%20and%20its%20basis%20at%20two%20instants%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-1%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20A%20body%20with%20its%20basis%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%2C%20%5Chat%7B%5Cmathbf%7Be%7D%7D_2%2C%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24%20at%20two%20instants%2C%20described%20in%20the%20laboratory's%20basis%20%24%5Chat%7B%5Cmathbf%7Bi%7D%7D%2C%20%5Chat%7B%5Cmathbf%7Bj%7D%7D%2C%20%5Chat%7B%5Cmathbf%7Bk%7D%7D%24.%3C%2Fspan%3E%0A%0A%20%20%20%20Everything%20about%20the%20body's%20rotation%20is%20in%20how%20this%20basis%20turns.%20The%20position%20of%20the%20body%20is%20a%20separate%20matter%2C%20carried%20by%20the%20origin%20of%20the%20basis.%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%20Axis%20of%20rotation%0A%0A%20%20%20%20As%20in%20planar%20movement%2C%20the%20angular%20velocity%20is%20a%20vector%20perpendicular%20to%20the%20plane%20of%20the%20rotation.%20The%20line%20in%20the%20direction%20of%20the%20angular%20velocity%20vector%20is%20known%20as%20the%20axis%20of%20rotation.%0A%0A%20%20%20%20The%20rotation%20between%20two%20frames%20of%20reference%20is%20characterized%20by%20the%20rotation%20matrix%20%24%5Cmathbf%7BR%7D%24%20obtained%20by%20stacking%20the%20versors%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%2C%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_2%24%20and%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24%2C%20written%20in%20the%20laboratory's%20basis%2C%20in%20the%20columns%20of%20the%20matrix%20(for%20a%20review%20of%20rotation%20matrices%2C%20see%20%5BRigid-body%20transformations%20in%20a%20plane%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_2d.py)%20and%20%5BRigid-body%20transformations%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_3d.py)).%0A%0A%20%20%20%20A%20vector%20in%20the%20direction%20of%20the%20axis%20of%20rotation%20is%20a%20vector%20that%20does%20not%20change%20after%20the%20rotation.%20That%20is%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cvec%7B%5Cmathbf%7Bv%7D%7D%20%3D%20%5Cmathbf%7BR%7D%5C%2C%5Cvec%7B%5Cmathbf%7Bv%7D%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20This%20vector%20is%20the%20eigenvector%20of%20the%20rotation%20matrix%20%24%5Cmathbf%7BR%7D%24%20with%20eigenvalue%20equal%20to%20one.%0A%0A%20%20%20%20Below%2C%20the%20yellow%20arrow%20shows%20the%20axis%20of%20rotation%20between%20the%20reference%20frame%20%24%5Chat%7B%5Cmathbf%7Bi%7D%7D%2C%20%5Chat%7B%5Cmathbf%7Bj%7D%7D%2C%20%5Chat%7B%5Cmathbf%7Bk%7D%7D%24%20(coloured%20arrows)%20and%20the%20reference%20frame%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%2C%20%5Chat%7B%5Cmathbf%7Be%7D%7D_2%2C%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24%20(black%20arrows)%2C%20obtained%20by%20rotating%20the%20first%20one%20by%20%24%5Cgamma%24%20about%20%24%5Cmathbf%7BZ%7D%24%2C%20then%20by%20%24%5Calpha%24%20about%20%24%5Cmathbf%7BX%7D%24%2C%20then%20by%20%24%5Cbeta%24%20about%20%24%5Cmathbf%7BY%7D%24%2C%20all%20about%20the%20fixed%20axes%20of%20the%20laboratory.%20Use%20the%20sliders%20to%20change%20the%20angles.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(sym)%3A%0A%20%20%20%20_a%2C%20_b%2C%20_g%20%3D%20sym.symbols(%22alpha%2C%20beta%2C%20gamma%22)%0A%0A%20%20%20%20%23%20Elemental%20rotation%20matrices%20of%20xyz%20in%20relation%20to%20XYZ%3A%0A%20%20%20%20_RX%20%3D%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20sym.cos(_a)%2C%20-sym.sin(_a)%5D%2C%20%5B0%2C%20sym.sin(_a)%2C%20sym.cos(_a)%5D%5D)%0A%20%20%20%20_RY%20%3D%20sym.Matrix(%5B%5Bsym.cos(_b)%2C%200%2C%20sym.sin(_b)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B-sym.sin(_b)%2C%200%2C%20sym.cos(_b)%5D%5D)%0A%20%20%20%20_RZ%20%3D%20sym.Matrix(%5B%5Bsym.cos(_g)%2C%20-sym.sin(_g)%2C%200%5D%2C%20%5Bsym.sin(_g)%2C%20sym.cos(_g)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%0A%20%20%20%20%23%20Rotation%20matrix%20of%20xyz%20in%20relation%20to%20XYZ%3A%0A%20%20%20%20rotation_matrix%20%3D%20sym.lambdify((_a%2C%20_b%2C%20_g)%2C%20_RY%20%40%20_RX%20%40%20_RZ%2C%20%22numpy%22)%0A%20%20%20%20return%20(rotation_matrix%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20alpha_slider%20%3D%20mo.ui.slider(-180%2C%20180%2C%20step%3D5%2C%20value%3D0%2C%20label%3D%22%CE%B1%2C%20about%20X%20%5Bdegrees%5D%22)%0A%20%20%20%20beta_slider%20%3D%20mo.ui.slider(-180%2C%20180%2C%20step%3D5%2C%20value%3D0%2C%20label%3D%22%CE%B2%2C%20about%20Y%20%5Bdegrees%5D%22)%0A%20%20%20%20gamma_slider%20%3D%20mo.ui.slider(-180%2C%20180%2C%20step%3D5%2C%20value%3D45%2C%20label%3D%22%CE%B3%2C%20about%20Z%20%5Bdegrees%5D%22)%0A%20%20%20%20mo.vstack(%5Balpha_slider%2C%20beta_slider%2C%20gamma_slider%5D)%0A%20%20%20%20return%20alpha_slider%2C%20beta_slider%2C%20gamma_slider%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20from%20notebook_resources%20import%20repo_file%0A%20%20%20%20except%20ModuleNotFoundError%20as%20_error%3A%0A%20%20%20%20%20%20%20%20if%20_error.name%20!%3D%20%22notebook_resources%22%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%0A%20%20%20%20%20%20%20%20raise%20ModuleNotFoundError(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22This%20notebook%20needs%20notebook_resources.py.%20Download%20it%20from%3A%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fraw.githubusercontent.com%2FBMClab%2FBMC%2Fmaster%2Ffunctions%2Fnotebook_resources.py%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Save%20it%20in%20the%20same%20folder%20as%20this%20notebook%2C%20then%20rerun%20this%20cell.%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22notebook_resources%22%2C%0A%20%20%20%20%20%20%20%20)%20from%20None%0A%20%20%20%20return%20(repo_file%2C)%0A%0A%0A%40app.cell%0Adef%20_(repo_file)%3A%0A%20%20%20%20import%20sys%0A%0A%20%20%20%20_functions%20%3D%20%5Brepo_file(f%22functions%2F%7B_m%7D.py%22)%20for%20_m%20in%20(%22CCSbasis%22%2C%20%22read_trc%22)%5D%0A%20%20%20%20sys.path.insert(0%2C%20str(_functions%5B0%5D.parent))%20%20%23%20add%20to%20pythonpath%0A%20%20%20%20from%20CCSbasis%20import%20CCSbasis%0A%20%20%20%20from%20read_trc%20import%20read_trc%0A%0A%20%20%20%20return%20CCSbasis%2C%20read_trc%0A%0A%0A%40app.cell%0Adef%20_(CCSbasis%2C%20alpha_slider%2C%20beta_slider%2C%20gamma_slider%2C%20np%2C%20rotation_matrix)%3A%0A%20%20%20%20_R%20%3D%20rotation_matrix(%0A%20%20%20%20%20%20%20%20np.radians(alpha_slider.value)%2C%20np.radians(beta_slider.value)%2C%20np.radians(gamma_slider.value)%0A%20%20%20%20)%0A%0A%20%20%20%20_e1%20%3D%20np.array(%5B%5B1%2C%200%2C%200%5D%5D)%0A%20%20%20%20_e2%20%3D%20np.array(%5B%5B0%2C%201%2C%200%5D%5D)%0A%20%20%20%20_e3%20%3D%20np.array(%5B%5B0%2C%200%2C%201%5D%5D)%0A%0A%20%20%20%20_basis%20%3D%20np.vstack((_e1%2C%20_e2%2C%20_e3))%0A%20%20%20%20_basis_rot%20%3D%20_R%20%40%20_basis%0A%20%20%20%20_lv%2C%20_v%20%3D%20np.linalg.eig(_R)%0A%0A%20%20%20%20print(%22Eigenvalues%20of%20R%3A%22%2C%20_lv.round(4))%0A%20%20%20%20if%20np.isclose(_lv%2C%201).sum()%20%3D%3D%203%3A%20%20%23%20no%20rotation%3A%20every%20direction%20is%20unchanged%0A%20%20%20%20%20%20%20%20print(%22No%20rotation%3A%20R%20is%20the%20identity%20matrix%2C%20and%20there%20is%20no%20axis%20to%20find.%22)%0A%20%20%20%20%20%20%20%20_ccs%20%3D%20CCSbasis(Oijk%3Dnp.array(%5B0%2C%200%2C%200%5D)%2C%20Oxyz%3Dnp.array(%5B0%2C%200%2C%200%5D)%2C%20ijk%3D_basis.T%2C%20xyz%3D_basis_rot.T)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20_axis_of_rotation%20%3D%20%5Bnp.real(np.squeeze(_v%5B%3A%2C%20np.isclose(_lv%2C%201)%5D))%5D%0A%20%20%20%20%20%20%20%20print(%22Axis%20of%20rotation%20(eigenvector%20of%20R%20with%20eigenvalue%201)%3A%22%2C%20_axis_of_rotation%5B0%5D.round(4))%0A%20%20%20%20%20%20%20%20_ccs%20%3D%20CCSbasis(%0A%20%20%20%20%20%20%20%20%20%20%20%20Oijk%3Dnp.array(%5B0%2C%200%2C%200%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20Oxyz%3Dnp.array(%5B0%2C%200%2C%200%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20ijk%3D_basis.T%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20xyz%3D_basis_rot.T%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20vector%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20point%3D_axis_of_rotation%2C%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%20With%20the%20default%20angles%2C%20a%20rotation%20of%20%2445%5E%5Ccirc%24%20about%20%24%5Cmathbf%7BZ%7D%24%20alone%2C%20the%20axis%20is%20%24%5Cmathbf%7BZ%7D%24%20itself%2C%20%24%5B0%2C%200%2C%201%5D%24.%20Try%20the%20sliders%3A%20whatever%20the%20three%20angles%2C%20the%20yellow%20arrow%20is%20a%20single%20line.%20Notice%20also%20the%20other%20two%20eigenvalues%3A%20they%20are%20complex.%0A%0A%20%20%20%20**Exercise%201.**%20Show%20that%20a%20rotation%20by%20an%20angle%20%24%5Ctheta%24%20about%20%24%5Cmathbf%7BZ%7D%24%20has%20the%20eigenvalues%20%241%24%20and%20%24%5Ccos%5Ctheta%20%5Cpm%20i%5Csin%5Ctheta%24%2C%20and%20check%20them%20against%20the%20eigenvalues%20printed%20for%20the%20default%20%2445%5E%5Ccirc%24.%20Then%20use%20the%20fact%20that%20the%20trace%20of%20a%20matrix%20is%20the%20sum%20of%20its%20eigenvalues%20to%20find%20%24%5Coperatorname%7Btr%7D%5Cmathbf%7BR%7D%24%20in%20terms%20of%20%24%5Ctheta%24.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%201%0A%0A%20%20%20%20For%20a%20rotation%20about%20%24%5Cmathbf%7BZ%7D%24%2C%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cmathbf%7BR%7D%20-%20%5Clambda%5Cmathbf%7BI%7D%20%3D%20%5Cbegin%7Bbmatrix%7D%5Ccos%5Ctheta%20-%20%5Clambda%20%26%20-%5Csin%5Ctheta%20%26%200%20%5C%5C%20%5Csin%5Ctheta%20%26%20%5Ccos%5Ctheta%20-%20%5Clambda%20%26%200%20%5C%5C%200%20%26%200%20%26%201%20-%20%5Clambda%5Cend%7Bbmatrix%7D%2C%0A%20%20%20%20%5Cqquad%0A%20%20%20%20%5Cdet(%5Cmathbf%7BR%7D%20-%20%5Clambda%5Cmathbf%7BI%7D)%20%3D%20(1%20-%20%5Clambda)%5Cleft%5B(%5Ccos%5Ctheta%20-%20%5Clambda)%5E2%20%2B%20%5Csin%5E2%5Ctheta%5Cright%5D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20determinant%20is%20zero%20for%20%24%5Clambda%20%3D%201%24%20(the%20axis)%20and%20for%20%24(%5Ccos%5Ctheta%20-%20%5Clambda)%5E2%20%3D%20-%5Csin%5E2%5Ctheta%24%2C%20that%20is%2C%20%24%5Clambda%20%3D%20%5Ccos%5Ctheta%20%5Cpm%20i%5Csin%5Ctheta%20%3D%20e%5E%7B%5Cpm%20i%5Ctheta%7D%24.%20For%20%24%5Ctheta%20%3D%2045%5E%5Ccirc%24%20that%20is%20%240.7071%20%5Cpm%200.7071i%24%2C%20as%20printed.%20Only%20directions%20along%20the%20axis%20are%20left%20unchanged%3B%20no%20other%20real%20direction%20is.%0A%0A%20%20%20%20The%20trace%20is%20the%20sum%20of%20the%20eigenvalues%2C%20so%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Coperatorname%7Btr%7D%5Cmathbf%7BR%7D%20%3D%201%20%2B%20e%5E%7Bi%5Ctheta%7D%20%2B%20e%5E%7B-i%5Ctheta%7D%20%3D%201%20%2B%202%5Ccos%5Ctheta%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Every%20rotation%20about%20any%20axis%20is%20a%20rotation%20about%20%24%5Cmathbf%7BZ%7D%24%20written%20in%20another%20basis%2C%20and%20a%20change%20of%20basis%20does%20not%20change%20the%20eigenvalues%2C%20so%20this%20holds%20for%20every%20rotation%20matrix.%20It%20is%20the%20formula%20used%20for%20the%20angle%20in%20the%20next%20cell.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20The%20eigenvector%20gives%20the%20line%20of%20the%20axis%2C%20but%20not%20which%20way%20along%20it%20the%20body%20turned%3A%20%24-%5Cvec%7B%5Cmathbf%7Bv%7D%7D%24%20is%20an%20eigenvector%20as%20well%2C%20and%20NumPy%20may%20return%20either.%20To%20get%20a%20direction%20and%20an%20angle%20that%20belong%20together%2C%20use%20the%20matrix%20itself.%20The%20angle%20comes%20from%20the%20trace%2C%20and%20the%20axis%2C%20pointing%20so%20that%20the%20rotation%20is%20counterclockwise%20by%20the%20right-hand%20rule%2C%20from%20the%20antisymmetric%20part%20of%20%24%5Cmathbf%7BR%7D%24%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Ctheta%20%3D%20%5Carccos%5Cleft(%5Cfrac%7B%5Coperatorname%7Btr%7D%5Cmathbf%7BR%7D%20-%201%7D%7B2%7D%5Cright)%2C%0A%20%20%20%20%5Cqquad%0A%20%20%20%20%5Chat%7B%5Cmathbf%7Bu%7D%7D%20%3D%20%5Cfrac%7B1%7D%7B2%5Csin%5Ctheta%7D%5Cbegin%7Bbmatrix%7D%20R_%7B32%7D%20-%20R_%7B23%7D%20%5C%5C%20R_%7B13%7D%20-%20R_%7B31%7D%20%5C%5C%20R_%7B21%7D%20-%20R_%7B12%7D%20%5Cend%7Bbmatrix%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20valid%20for%20%240%20%3C%20%5Ctheta%20%3C%20180%5E%5Ccirc%24.%20Conversely%2C%20Rodrigues'%20formula%20builds%20the%20rotation%20matrix%20from%20an%20axis%20and%20an%20angle.%20Here%20are%20both%2C%20and%20an%20elemental%20rotation%20about%20one%20of%20the%20fixed%20axes%2C%20as%20reusable%20functions%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20axis_angle(R)%3A%0A%20%20%20%20%22%22%22Axis%20(versor)%20and%20angle%20%5Bdegrees%5D%20of%20the%20rotation%20matrix%20R%2C%20for%200%20%3C%20angle%20%3C%20180.%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20R%20%3D%20np.asarray(R%2C%20dtype%3Dfloat)%0A%20%20%20%20theta%20%3D%20np.arccos(np.clip((np.trace(R)%20-%201)%20%2F%202%2C%20-1%2C%201))%0A%20%20%20%20u%20%3D%20np.array(%5BR%5B2%2C%201%5D%20-%20R%5B1%2C%202%5D%2C%20R%5B0%2C%202%5D%20-%20R%5B2%2C%200%5D%2C%20R%5B1%2C%200%5D%20-%20R%5B0%2C%201%5D%5D)%20%2F%20(2%20*%20np.sin(theta))%0A%20%20%20%20return%20u%2C%20np.degrees(theta)%0A%0A%0A%40app.function%0Adef%20rodrigues(u%2C%20angle)%3A%0A%20%20%20%20%22%22%22Rotation%20matrix%20for%20a%20rotation%20by%20%60angle%60%20%5Brad%5D%20about%20the%20axis%20%60u%60.%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20u%20%3D%20np.asarray(u%2C%20dtype%3Dfloat)%20%2F%20np.linalg.norm(u)%0A%20%20%20%20K%20%3D%20np.array(%5B%5B0%2C%20-u%5B2%5D%2C%20u%5B1%5D%5D%2C%20%5Bu%5B2%5D%2C%200%2C%20-u%5B0%5D%5D%2C%20%5B-u%5B1%5D%2C%20u%5B0%5D%2C%200%5D%5D)%0A%20%20%20%20return%20np.eye(3)%20%2B%20np.sin(angle)%20*%20K%20%2B%20(1%20-%20np.cos(angle))%20*%20K%20%40%20K%0A%0A%0A%40app.function%0Adef%20elemental(axis%2C%20angle)%3A%0A%20%20%20%20%22%22%22Rotation%20matrix%20for%20a%20rotation%20by%20%60angle%60%20%5Bdegrees%5D%20about%20the%20fixed%20axis%20'X'%2C%20'Y'%20or%20'Z'.%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20u%20%3D%20%7B%22X%22%3A%20%5B1%2C%200%2C%200%5D%2C%20%22Y%22%3A%20%5B0%2C%201%2C%200%5D%2C%20%22Z%22%3A%20%5B0%2C%200%2C%201%5D%7D%5Baxis%5D%0A%20%20%20%20return%20rodrigues(u%2C%20np.radians(angle))%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20One%20rotation%20is%20always%20enough%0A%0A%20%20%20%20That%20the%20yellow%20arrow%20is%20always%20a%20single%20line%20is%20%5BEuler's%20rotation%20theorem%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FEuler%2527s_rotation_theorem)%3A%20however%20a%20rigid%20body%20has%20been%20turned%2C%20its%20final%20orientation%20can%20be%20reached%20from%20the%20initial%20one%20by%20a%20single%20rotation%20about%20a%20single%20axis.%20Three%20Cardan%20angles%20and%20one%20axis%20with%20one%20angle%20are%20two%20descriptions%20of%20the%20same%20change%20of%20orientation.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20a%20body%20is%20turned%20by%20%2445%5E%5Ccirc%24%20about%20%24%5Cmathbf%7BZ%7D%24%2C%20then%20%2445%5E%5Ccirc%24%20about%20%24%5Cmathbf%7BX%7D%24%2C%20then%20%2445%5E%5Ccirc%24%20about%20%24%5Cmathbf%7BY%7D%24.%20What%20is%20the%20angle%20of%20the%20single%20rotation%20that%20does%20the%20same%3F%20Is%20it%20%24135%5E%5Ccirc%24%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20rotation_matrix)%3A%0A%20%20%20%20_R3%20%3D%20rotation_matrix(np.radians(45)%2C%20np.radians(45)%2C%20np.radians(45))%20%20%23%20Z%2C%20then%20X%2C%20then%20Y%0A%20%20%20%20_u%2C%20_theta%20%3D%20axis_angle(_R3)%0A%20%20%20%20print(f%22Z%2C%20then%20X%2C%20then%20Y%3A%20%7B_theta%3A.1f%7D%20degrees%20about%20%7B_u.round(3)%7D%22)%0A%20%20%20%20print(%22Rodrigues'%20formula%20gives%20back%20the%20same%20matrix%3A%22%2C%20np.allclose(rodrigues(_u%2C%20np.radians(_theta))%2C%20_R3))%0A%0A%20%20%20%20_R3_reversed%20%3D%20elemental(%22Z%22%2C%2045)%20%40%20elemental(%22X%22%2C%2045)%20%40%20elemental(%22Y%22%2C%2045)%20%20%23%20Y%2C%20then%20X%2C%20then%20Z%0A%20%20%20%20_u%2C%20_theta%20%3D%20axis_angle(_R3_reversed)%0A%20%20%20%20print(f%22Y%2C%20then%20X%2C%20then%20Z%3A%20%7B_theta%3A.1f%7D%20degrees%20about%20%7B_u.round(3)%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Three%20rotations%20of%20%2445%5E%5Ccirc%24%20amount%20to%20a%20single%20rotation%20of%20only%20%2464.7%5E%5Ccirc%24%2C%20about%20an%20axis%20close%20to%20%24%5Cmathbf%7BX%7D%24.%20Done%20in%20the%20reverse%20order%2C%20the%20same%20three%20rotations%20give%20%2485.8%5E%5Ccirc%24%20about%20a%20quite%20different%20axis.%20Angles%20of%20finite%20rotations%20about%20different%20axes%20do%20not%20simply%20add%20up.%0A%0A%20%20%20%20**Exercise%202.**%20A%20forearm%20held%20horizontally%20is%20turned%20by%20%2490%5E%5Ccirc%24%20about%20the%20laboratory's%20%24%5Cmathbf%7BX%7D%24%20axis%20and%20then%20by%20%2490%5E%5Ccirc%24%20about%20the%20laboratory's%20%24%5Cmathbf%7BY%7D%24%20axis.%20Find%20the%20axis%20and%20the%20angle%20of%20the%20single%20rotation%20that%20takes%20it%20from%20the%20first%20orientation%20to%20the%20last.%20Before%20computing%2C%20guess%20whether%20the%20angle%20is%20smaller%20or%20larger%20than%20%2490%5E%5Ccirc%20%2B%2090%5E%5Ccirc%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%2C%20np)%3A%0A%20%20%20%20_R%20%3D%20elemental(%22Y%22%2C%2090)%20%40%20elemental(%22X%22%2C%2090)%20%20%23%20X%20first%2C%20then%20Y%20(fixed%20axes)%0A%20%20%20%20_u%2C%20_theta%20%3D%20axis_angle(_R)%0A%20%20%20%20_R_check%20%3D%20rodrigues(_u%2C%20np.radians(_theta))%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.vstack(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rf%22%22%22%0A%20%20%20%20Each%20new%20rotation%20about%20a%20fixed%20axis%20multiplies%20the%20matrix%20from%20the%20left%2C%20so%20%24%5Cmathbf%7B%7BR%7D%7D%20%3D%20%5Cmathbf%7B%7BR_Y%7D%7D(90%5E%5Ccirc)%5C%2C%5Cmathbf%7B%7BR_X%7D%7D(90%5E%5Ccirc)%24%2C%20and%20%60axis_angle%60%20gives%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Ctheta%20%3D%20%7B_theta%3A.1f%7D%5E%5Ccirc%20%5Cquad%20%5Ctext%7B%7Babout%7D%7D%20%5Cquad%20%5Chat%7B%7B%5Cmathbf%7B%7Bu%7D%7D%7D%7D%20%3D%20%5B%7B_u%5B0%5D%3A.4f%7D%2C%5C%3B%20%7B_u%5B1%5D%3A.4f%7D%2C%5C%3B%20%7B_u%5B2%5D%3A.4f%7D%5D%20%3D%20%5Cfrac%7B%7B1%7D%7D%7B%7B%5Csqrt%7B%7B3%7D%7D%7D%7D%5B1%2C%5C%3B%201%2C%5C%3B%20-1%5D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Rodrigues'%20formula%20with%20this%20axis%20and%20angle%20gives%20back%20the%20same%20matrix%3A%20%7Bnp.allclose(_R_check%2C%20_R)%7D.%20Two%20quarter%20turns%20about%20perpendicular%20axes%20are%20a%20single%20turn%20of%20only%20%24120%5E%5Ccirc%24%2C%20a%20third%20of%20a%20full%20turn%2C%20about%20a%20diagonal%20of%20the%20cube%20defined%20by%20the%20axes.%20Repeat%20it%20three%20times%20and%20the%20body%20is%20back%20where%20it%20started.%0A%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%24%24%5Cmathbf%7BR%7D%20%3D%20%5Cmathbf%7BR_Y%7D(90%5E%5Ccirc)%5C%2C%5Cmathbf%7BR_X%7D(90%5E%5Ccirc)%20%3D%20%5Cbegin%7Bbmatrix%7D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20r%22%20%5C%5C%20%22.join(%22%20%26%20%22.join(f%22%7B_v%3Ag%7D%22%20for%20_v%20in%20_row)%20for%20_row%20in%20np.round(_R%2C%204)%20%2B%200.0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20r%22%5Cend%7Bbmatrix%7D%24%24%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Finite%20rotations%20are%20not%20vectors%0A%0A%20%20%20%20A%20tempting%20idea%20is%20to%20represent%20a%20rotation%20by%20a%20vector%3A%20along%20the%20axis%2C%20with%20a%20length%20equal%20to%20the%20angle.%20For%20rotations%20about%20the%20same%20axis%20this%20works%20perfectly%2C%20since%20%2430%5E%5Ccirc%24%20followed%20by%20%2415%5E%5Ccirc%24%20is%20%2445%5E%5Ccirc%24%2C%20which%20is%20why%20it%20works%20in%20a%20plane%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)).%20Let's%20see%20what%20happens%20with%20two%20different%20axes%2C%20for%20large%20and%20for%20small%20angles.%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%20def%20_rotation_vector(R)%3A%0A%20%20%20%20%20%20%20%20_u%2C%20_theta%20%3D%20axis_angle(R)%0A%20%20%20%20%20%20%20%20return%20_u%20*%20_theta%20%20%23%20degrees%0A%0A%20%20%20%20for%20_deg%20in%20%5B45%2C%201%5D%3A%0A%20%20%20%20%20%20%20%20_composed%20%3D%20elemental(%22Y%22%2C%20_deg)%20%40%20elemental(%22X%22%2C%20_deg)%20%20%23%20X%20first%2C%20then%20Y%0A%20%20%20%20%20%20%20%20_naive_sum%20%3D%20_rotation_vector(elemental(%22X%22%2C%20_deg))%20%2B%20_rotation_vector(elemental(%22Y%22%2C%20_deg))%0A%20%20%20%20%20%20%20%20print(f%22%7B_deg%3A2d%7D%20degrees%20about%20X%2C%20then%20%7B_deg%7D%20about%20Y%3A%22)%0A%20%20%20%20%20%20%20%20print(%22%20%20%20rotation%20vector%20of%20the%20result%20%5Bdegrees%5D%3A%22%2C%20_rotation_vector(_composed).round(4))%0A%20%20%20%20%20%20%20%20print(%22%20%20%20sum%20of%20the%20two%20rotation%20vectors%3A%20%20%20%20%20%20%20%20%22%2C%20_naive_sum.round(4))%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20For%20%2445%5E%5Ccirc%24%20the%20result%20is%20far%20from%20the%20sum%3A%20a%20different%20angle%20about%20each%20axis%2C%20and%20a%20%24-17.7%5E%5Ccirc%24%20component%20about%20%24%5Cmathbf%7BZ%7D%24%20that%20neither%20rotation%20had.%20For%20%241%5E%5Ccirc%24%20the%20sum%20is%20almost%20right%3B%20the%20error%2C%20%24-0.0087%5E%5Ccirc%24%2C%20is%20smaller%20than%20the%20angles%20by%20a%20factor%20of%20about%20a%20hundred.%20The%20smaller%20the%20rotations%2C%20the%20better%20they%20add%2C%20and%20the%20order%20in%20which%20they%20are%20done%20stops%20mattering.%0A%0A%20%20%20%20That%20is%20what%20makes%20angular%20velocity%20a%20vector.%20It%20describes%20the%20infinitesimal%20rotation%20of%20a%20body%20in%20an%20infinitesimal%20time%2C%20%24d%5Ctheta%2Fdt%24%2C%20and%20infinitesimal%20rotations%20add%20like%20vectors.%20Angular%20velocities%20about%20different%20axes%20can%20be%20added%2C%20and%20the%20order%20does%20not%20matter%3B%20angles%20about%20different%20axes%20cannot.%0A%0A%20%20%20%20**Guiding%20questions%201.**%0A%0A%20%20%20%201.%20Why%20does%20the%20order%20of%20two%20rotations%20stop%20mattering%20when%20the%20rotations%20are%20small%3F%0A%20%20%20%202.%20The%20three%20Cardan%20angles%20are%20angles%20of%20*finite*%20rotations%20about%20different%20axes.%20What%20does%20that%20suggest%20about%20adding%20up%20their%20derivatives%3F%0A%20%20%20%203.%20Go%20back%20to%20your%20pen%20in%20Challenge%200.%20If%20the%20spin%20and%20the%20swing%20each%20have%20an%20angular%20velocity%2C%20what%20is%20the%20angular%20velocity%20of%20the%20pen%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%20Computing%20the%20angular%20velocity%0A%0A%20%20%20%20The%20angular%20velocity%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20is%20in%20the%20direction%20of%20the%20axis%20of%20rotation%20(hence%20it%20is%20parallel%20to%20the%20axis%20of%20rotation)%20and%20can%20be%20described%20in%20the%20basis%20fixed%20in%20the%20body%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%3D%20%5Comega_1%5Chat%7B%5Cmathbf%7Be%7D%7D_1%20%2B%20%5Comega_2%5Chat%7B%5Cmathbf%7Be%7D%7D_2%20%2B%20%5Comega_3%5Chat%7B%5Cmathbf%7Be%7D%7D_3%0A%20%20%20%20%24%24%0A%0A%20%20%20%20So%2C%20we%20must%20find%20%24%5Comega_1%24%2C%20%24%5Comega_2%24%20and%20%24%5Comega_3%24%2C%20and%20we%20will%20do%20it%20using%20only%20the%20versors%20of%20the%20basis%20and%20their%20derivatives.%0A%0A%20%20%20%20Recall%20that%20the%20angular%20velocity%20is%20described%20as%20a%20vector%20perpendicular%20to%20the%20plane%20of%20the%20rotation%3A%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_1%20%3D%20%5Cfrac%7Bd%5Ctheta_1%7D%7Bdt%7D%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%2C%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_2%20%3D%20%5Cfrac%7Bd%5Ctheta_2%7D%7Bdt%7D%5Chat%7B%5Cmathbf%7Be%7D%7D_2%24%20and%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_3%20%3D%20%5Cfrac%7Bd%5Ctheta_3%7D%7Bdt%7D%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24%2C%20where%20%24%5Ctheta_1%24%2C%20%24%5Ctheta_2%24%20and%20%24%5Ctheta_3%24%20are%20the%20infinitesimal%20angles%20the%20body%20turns%20about%20each%20of%20its%20axes.%0A%0A%20%20%20%20Note%20also%20that%20the%20derivative%20of%20the%20angle%20%24%5Ctheta_1%24%20can%20be%20described%20as%20the%20projection%20of%20the%20vector%20%24%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_2%7D%7Bdt%7D%24%20on%20the%20vector%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24%3A%20as%20the%20body%20turns%20about%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%2C%20the%20tip%20of%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_2%24%20moves%20towards%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24.%20This%20can%20be%20written%20with%20the%20scalar%20product%20between%20these%20vectors%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cfrac%7Bd%5Ctheta_1%7D%7Bdt%7D%20%3D%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_2%7D%7Bdt%7D%5Ccdot%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%0A%20%20%20%20%24%24%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%2FderivVersor.png%3Fraw%3D1%22%20width%3D350%20alt%3D%22derivatives%20of%20the%20versors%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.%20The%20versors%20of%20the%20body's%20basis%20(black)%2C%20the%20same%20versors%20a%20moment%20later%20(red)%2C%20and%20their%20derivatives%20(blue).%20The%20rotation%20%24%5Ctheta_1%24%20about%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%20moves%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_2%24%20towards%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24.%3C%2Fspan%3E%0A%0A%20%20%20%20Similarly%2C%20the%20same%20is%20valid%20for%20the%20angles%20in%20the%20other%20two%20directions%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cfrac%7Bd%5Ctheta_2%7D%7Bdt%7D%20%3D%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_3%7D%7Bdt%7D%5Ccdot%20%5Chat%7B%5Cmathbf%7Be%7D%7D_1%2C%0A%20%20%20%20%5Cqquad%0A%20%20%20%20%5Cfrac%7Bd%5Ctheta_3%7D%7Bdt%7D%20%3D%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_1%7D%7Bdt%7D%5Ccdot%20%5Chat%7B%5Cmathbf%7Be%7D%7D_2%0A%20%20%20%20%24%24%0A%0A%20%20%20%20So%2C%20we%20can%20write%20the%20angular%20velocity%20as%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%3D%20%5Cleft(%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_2%7D%7Bdt%7D%5Ccdot%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%5Cright)%20%5Chat%7B%5Cmathbf%7Be%7D%7D_1%20%2B%20%5Cleft(%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_3%7D%7Bdt%7D%5Ccdot%20%5Chat%7B%5Cmathbf%7Be%7D%7D_1%5Cright)%20%5Chat%7B%5Cmathbf%7Be%7D%7D_2%20%2B%20%5Cleft(%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_1%7D%7Bdt%7D%5Ccdot%20%5Chat%7B%5Cmathbf%7Be%7D%7D_2%5Cright)%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%0A%20%20%20%20%24%24%0A%0A%20%20%20%20**Exercise%203.**%20A%20body%20rotates%20in%20the%20horizontal%20plane%20about%20the%20fixed%20%24%5Cmathbf%7BZ%7D%24%20axis%2C%20by%20an%20angle%20%24%5Ctheta(t)%24%2C%20so%20that%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%20%3D%20%5B%5Ccos%5Ctheta%2C%20%5Csin%5Ctheta%2C%200%5D%24%2C%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_2%20%3D%20%5B-%5Csin%5Ctheta%2C%20%5Ccos%5Ctheta%2C%200%5D%24%20and%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_3%20%3D%20%5B0%2C%200%2C%201%5D%24.%20Apply%20the%20formula%20above%20and%20show%20that%20it%20gives%20back%20the%20planar%20angular%20velocity.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%203%0A%0A%20%20%20%20With%20the%20chain%20rule%2C%20%24%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_1%7D%7Bdt%7D%20%3D%20%5Cdot%7B%5Ctheta%7D%5C%2C%5B-%5Csin%5Ctheta%2C%20%5Ccos%5Ctheta%2C%200%5D%20%3D%20%5Cdot%7B%5Ctheta%7D%5C%2C%5Chat%7B%5Cmathbf%7Be%7D%7D_2%24%2C%20%24%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_2%7D%7Bdt%7D%20%3D%20%5Cdot%7B%5Ctheta%7D%5C%2C%5B-%5Ccos%5Ctheta%2C%20-%5Csin%5Ctheta%2C%200%5D%20%3D%20-%5Cdot%7B%5Ctheta%7D%5C%2C%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%20and%20%24%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_3%7D%7Bdt%7D%20%3D%20%5Cvec%7B%5Cmathbf%7B0%7D%7D%24.%20Then%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Comega_1%20%3D%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_2%7D%7Bdt%7D%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_3%20%3D%200%2C%0A%20%20%20%20%5Cqquad%0A%20%20%20%20%5Comega_2%20%3D%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_3%7D%7Bdt%7D%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_1%20%3D%200%2C%0A%20%20%20%20%5Cqquad%0A%20%20%20%20%5Comega_3%20%3D%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_1%7D%7Bdt%7D%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_2%20%3D%20%5Cdot%7B%5Ctheta%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20so%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%3D%20%5Cdot%7B%5Ctheta%7D%5C%2C%5Chat%7B%5Cmathbf%7Be%7D%7D_3%20%3D%20%5Cdot%7B%5Ctheta%7D%5C%2C%5Chat%7B%5Cmathbf%7Bk%7D%7D%24%3A%20the%20angular%20velocity%20of%20planar%20motion%2C%20along%20the%20axis%20perpendicular%20to%20the%20plane%2C%20as%20in%20%5BKinematics%20of%20a%20rigid%20body%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_of_rigid_body.py).%20In%20a%20plane%2C%20and%20only%20there%2C%20the%20angular%20velocity%20is%20the%20derivative%20of%20one%20angle.%0A%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(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%20Why%20the%20formula%20works%0A%0A%20%20%20%20The%20argument%20with%20the%20figure%20can%20be%20made%20exact.%20In%20%5BKinematics%20of%20a%20rigid%20body%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_of_rigid_body.py)%2C%20the%20versors%20of%20a%20body%20rotating%20in%20a%20plane%20changed%20as%20%24d%5Chat%7B%5Cmathbf%7Bi%7D%7D'%2Fdt%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20%5Chat%7B%5Cmathbf%7Bi%7D%7D'%24.%20The%20same%20holds%20in%203D%20for%20every%20vector%20fixed%20in%20a%20rigid%20body%2C%20so%20for%20each%20versor%20of%20its%20basis%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_i%7D%7Bdt%7D%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20%5Chat%7B%5Cmathbf%7Be%7D%7D_i%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Then%2C%20with%20the%20scalar%20triple%20product%2C%20%24(%5Cvec%7B%5Cmathbf%7Ba%7D%7D%20%5Ctimes%20%5Cvec%7B%5Cmathbf%7Bb%7D%7D)%5Ccdot%5Cvec%7B%5Cmathbf%7Bc%7D%7D%20%3D%20%5Cvec%7B%5Cmathbf%7Ba%7D%7D%5Ccdot(%5Cvec%7B%5Cmathbf%7Bb%7D%7D%20%5Ctimes%20%5Cvec%7B%5Cmathbf%7Bc%7D%7D)%24%2C%20and%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_2%20%5Ctimes%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%20%3D%20%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%20for%20a%20right-handed%20basis%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_2%7D%7Bdt%7D%5Ccdot%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%20%3D%20%5Cleft(%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20%5Chat%7B%5Cmathbf%7Be%7D%7D_2%5Cright)%5Ccdot%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%5Ccdot%5Cleft(%5Chat%7B%5Cmathbf%7Be%7D%7D_2%20%5Ctimes%20%5Chat%7B%5Cmathbf%7Be%7D%7D_3%5Cright)%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_1%20%3D%20%5Comega_1%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20likewise%20for%20%24%5Comega_2%24%20and%20%24%5Comega_3%24.%20The%20formula%20needs%20the%20basis%20to%20be%20right-handed%3A%20with%20a%20left-handed%20basis%20every%20component%20comes%20out%20with%20the%20wrong%20sign.%0A%0A%20%20%20%20Note%20that%20the%20angular%20velocity%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20found%20this%20way%20is%20expressed%20in%20the%20reference%20frame%20of%20the%20object.%20If%20you%20want%20it%20described%20as%20a%20linear%20combination%20of%20the%20versors%20of%20the%20global%20basis%20%24%5Chat%7B%5Cmathbf%7Bi%7D%7D%24%2C%20%24%5Chat%7B%5Cmathbf%7Bj%7D%7D%24%20and%20%24%5Chat%7B%5Cmathbf%7Bk%7D%7D%24%2C%20multiply%20the%20vector%20of%20components%20by%20the%20rotation%20matrix%20formed%20by%20stacking%20each%20versor%20in%20a%20column%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7BG%7D%20%3D%20%5Cmathbf%7BR%7D%5C%2C%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7Bl%7D%20%3D%20%5Comega_1%5Chat%7B%5Cmathbf%7Be%7D%7D_1%20%2B%20%5Comega_2%5Chat%7B%5Cmathbf%7Be%7D%7D_2%20%2B%20%5Comega_3%5Chat%7B%5Cmathbf%7Be%7D%7D_3%0A%20%20%20%20%24%24%0A%0A%20%20%20%20There%20is%20also%20a%20compact%20formula%20that%20gives%20the%20global%20components%20directly.%20Since%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_i%20%5Ctimes%20(%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20%5Chat%7B%5Cmathbf%7Be%7D%7D_i)%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20-%20(%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_i)%5C%2C%5Chat%7B%5Cmathbf%7Be%7D%7D_i%24%2C%20summing%20over%20the%20three%20versors%20gives%20%243%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20-%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%2C%20so%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%3D%20%5Cfrac%7B1%7D%7B2%7D%5Csum_%7Bi%3D1%7D%5E%7B3%7D%20%5Chat%7B%5Cmathbf%7Be%7D%7D_i%20%5Ctimes%20%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_i%7D%7Bdt%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20We%20will%20use%20it%20as%20an%20independent%20check.%20Here%20is%20the%20dot-product%20formula%20as%20a%20function%2C%20for%20versors%20sampled%20at%20a%20constant%20rate%2C%20one%20row%20per%20instant.%20The%20derivatives%20are%20central%20differences%20from%20%60numpy.gradient%60%2C%20with%20%60edge_order%3D2%60%20so%20that%20the%20first%20and%20last%20samples%20are%20accurate%20too%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20angular_velocity(e1%2C%20e2%2C%20e3%2C%20dt)%3A%0A%20%20%20%20%22%22%22Components%20of%20the%20angular%20velocity%20in%20the%20body's%20own%20basis.%0A%0A%20%20%20%20%60e1%60%2C%20%60e2%60%2C%20%60e3%60%20hold%20the%20versors%20of%20a%20right-handed%20basis%20attached%20to%20the%0A%20%20%20%20body%2C%20one%20row%20per%20instant%2C%20sampled%20every%20%60dt%60%20seconds.%20Returns%20an%20array%0A%20%20%20%20with%20the%20components%20%5Bomega_1%2C%20omega_2%2C%20omega_3%5D%2C%20in%20rad%2Fs%2C%20one%20row%20per%0A%20%20%20%20instant.%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20de1dt%2C%20de2dt%2C%20de3dt%20%3D%20(np.gradient(e%2C%20dt%2C%20axis%3D0%2C%20edge_order%3D2)%20for%20e%20in%20(e1%2C%20e2%2C%20e3))%0A%20%20%20%20omega1%20%3D%20np.sum(de2dt%20*%20e3%2C%20axis%3D1)%0A%20%20%20%20omega2%20%3D%20np.sum(de3dt%20*%20e1%2C%20axis%3D1)%0A%20%20%20%20omega3%20%3D%20np.sum(de1dt%20*%20e2%2C%20axis%3D1)%0A%20%20%20%20return%20np.column_stack((omega1%2C%20omega2%2C%20omega3))%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20A%20spin%20we%20know%0A%0A%20%20%20%20Before%20trusting%20the%20formula%20with%20measured%20data%2C%20let's%20give%20it%20a%20motion%20with%20a%20known%20answer.%20A%20body%2C%20initially%20turned%20by%20%2430%5E%5Ccirc%24%20about%20%24%5Cmathbf%7BX%7D%24%2C%20spins%20at%20one%20revolution%20per%20second%2C%20%24%5Comega%20%3D%202%5Cpi%24%20rad%2Fs%2C%20about%20the%20fixed%20axis%20%24%5Chat%7B%5Cmathbf%7Bu%7D%7D%20%3D%20%5B1%2C%201%2C%201%5D%2F%5Csqrt%7B3%7D%24.%20We%20sample%20its%20basis%20at%20100%20Hz%20for%20one%20second.%0A%0A%20%20%20%20The%20angular%20velocity%20in%20the%20laboratory's%20basis%20is%20%242%5Cpi%5C%2C%5Chat%7B%5Cmathbf%7Bu%7D%7D%20%3D%20%5B3.6276%2C%203.6276%2C%203.6276%5D%24%20rad%2Fs%20at%20every%20instant.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20will%20the%20components%20in%20the%20*body's*%20basis%20be%20the%20same%20three%20numbers%3F%20Will%20they%20at%20least%20be%20constant%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_dt%20%3D%200.01%20%20%23%20s%2C%20100%20Hz%0A%20%20%20%20_t%20%3D%20np.arange(0%2C%201%20%2B%20_dt%20%2F%202%2C%20_dt)%0A%20%20%20%20_u%20%3D%20np.array(%5B1%2C%201%2C%201%5D)%20%2F%20np.sqrt(3)%0A%20%20%20%20_omega%20%3D%202%20*%20np.pi%20%20%23%20rad%2Fs%0A%0A%20%20%20%20_R0%20%3D%20rodrigues(%5B1%2C%200%2C%200%5D%2C%20np.radians(30))%20%20%23%20initial%20orientation%0A%20%20%20%20_Rs%20%3D%20np.array(%5Brodrigues(_u%2C%20_omega%20*%20_ti)%20%40%20_R0%20for%20_ti%20in%20_t%5D)%20%20%23%20versors%20in%20the%20columns%0A%20%20%20%20_e1%2C%20_e2%2C%20_e3%20%3D%20_Rs%5B%3A%2C%20%3A%2C%200%5D%2C%20_Rs%5B%3A%2C%20%3A%2C%201%5D%2C%20_Rs%5B%3A%2C%20%3A%2C%202%5D%0A%0A%20%20%20%20_omega_l%20%3D%20angular_velocity(_e1%2C%20_e2%2C%20_e3%2C%20_dt)%20%20%23%20body%20components%0A%20%20%20%20_omega_G%20%3D%20np.einsum(%22nij%2Cnj-%3Eni%22%2C%20_Rs%2C%20_omega_l)%20%20%23%20R%20omega_l%2C%20instant%20by%20instant%0A%0A%20%20%20%20_derivs%20%3D%20%5Bnp.gradient(_e%2C%20_dt%2C%20axis%3D0%2C%20edge_order%3D2)%20for%20_e%20in%20(_e1%2C%20_e2%2C%20_e3)%5D%0A%20%20%20%20_omega_G2%20%3D%200.5%20*%20sum(np.cross(_e%2C%20_d)%20for%20_e%2C%20_d%20in%20zip((_e1%2C%20_e2%2C%20_e3)%2C%20_derivs))%0A%0A%20%20%20%20print(%22Body%20components%20at%20t%20%3D%200%2C%200.5%20and%201%20s%20%5Brad%2Fs%5D%3A%22)%0A%20%20%20%20for%20_i%20in%20%5B0%2C%2050%2C%20100%5D%3A%0A%20%20%20%20%20%20%20%20print(%22%20%20%22%2C%20_omega_l%5B_i%5D.round(4))%0A%20%20%20%20print(%22Expected%20body%20components%2C%20R0%5ET%20(2%20pi%20u)%3A%22%2C%20(_R0.T%20%40%20(_omega%20*%20_u)).round(4))%0A%20%20%20%20print(f%22%5CnLargest%20error%20of%20the%20global%20components%3A%20%7Bnp.abs(_omega_G%20-%20_omega%20*%20_u).max()%3A.4f%7D%20rad%2Fs%22)%0A%20%20%20%20print(f%22Relative%20error%3A%20%7Bnp.abs(_omega_G%20-%20_omega%20*%20_u).max()%20%2F%20_omega%3A.1e%7D%3B%20(omega%20dt)%5E2%20%2F%206%20%3D%20%7B(_omega%20*%20_dt)%20**%202%20%2F%206%3A.1e%7D%22)%0A%20%20%20%20print(f%22Largest%20difference%20from%20the%20compact%20formula%3A%20%7Bnp.abs(_omega_G2%20-%20_omega_G).max()%3A.1e%7D%20rad%2Fs%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20body%20components%20are%20constant%2C%20%24%5B3.63%2C%204.96%2C%201.33%5D%24%20rad%2Fs%2C%20but%20they%20are%20not%20the%20laboratory's%20three%20equal%20numbers.%20For%20a%20rotation%20about%20a%20fixed%20axis%2C%20the%20axis%20stays%20put%20in%20the%20laboratory%20*and*%20in%20the%20body%2C%20since%20the%20body%20turns%20about%20it.%20Its%20direction%20in%20the%20body's%20basis%20is%20whatever%20it%20was%20at%20the%20start%2C%20%24%5Cmathbf%7BR%7D_0%5ET%5Chat%7B%5Cmathbf%7Bu%7D%7D%24%2C%20and%20the%20body%20components%20keep%20that%20value%20throughout.%20Multiplying%20by%20%24%5Cmathbf%7BR%7D%24%20at%20each%20instant%20brings%20them%20back%20to%20the%20laboratory's%20%24%5B3.6276%2C%203.6276%2C%203.6276%5D%24.%0A%0A%20%20%20%20The%20largest%20error%20is%200.005%20rad%2Fs%2C%20a%20relative%20error%20of%20%248%20%5Ctimes%2010%5E%7B-4%7D%24.%20It%20comes%20from%20the%20finite%20differences%3A%20the%20tip%20of%20a%20versor%20moves%20on%20a%20circle%2C%20and%20a%20central%20difference%20over%20an%20arc%20of%20angle%20%24%5Comega%5C%2C%5CDelta%20t%24%20underestimates%20its%20speed%20by%20a%20factor%20of%20about%20%241%20-%20(%5Comega%5CDelta%20t)%5E2%2F6%24.%20The%20compact%20formula%20agrees%20with%20the%20dot-product%20formula%20to%20within%20%242%20%5Ctimes%2010%5E%7B-4%7D%24%20rad%2Fs.%0A%0A%20%20%20%20**Challenge%201.**%20Halve%20the%20sampling%20interval%20and%20run%20the%20cell%20again.%20By%20what%20factor%20does%20the%20error%20change%3F%20Is%20that%20what%20%24(%5Comega%5C%2C%5CDelta%20t)%5E2%2F6%24%20predicts%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%20Example%3A%20adding%20angular%20velocities%20in%20the%20forearm%0A%0A%20%20%20%20Now%20a%20motion%20with%20two%20rotations%20at%20once%2C%20the%20situation%20of%20Challenge%200.%20The%20upper%20arm%20is%20held%20still%20and%20vertical%2C%20the%20elbow%20is%20flexed%20at%20%2490%5E%5Ccirc%24%2C%20and%20the%20forearm%20points%20forward%2C%20along%20the%20laboratory's%20%24%5Cmathbf%7BX%7D%24%20axis%2C%20with%20%24%5Cmathbf%7BY%7D%24%20upwards%20and%20%24%5Cmathbf%7BZ%7D%24%20to%20the%20right.%20For%200.3%20s%20the%20elbow%20flexes%20at%20a%20constant%20%24300%5E%5Ccirc%24%2Fs%20about%20its%20medio-lateral%20axis%2C%20%24%5Cmathbf%7BZ%7D%24%2C%20raising%20the%20hand%2C%20while%20the%20forearm%20pronates%20at%20a%20constant%20%24400%5E%5Ccirc%24%2Fs%20about%20its%20own%20long%20axis%2C%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24.%20The%20rates%20are%20round%20numbers%20chosen%20for%20the%20arithmetic%2C%20but%20of%20the%20order%20of%20those%20of%20quick%20everyday%20movements.%0A%0A%20%20%20%20The%20orientation%20of%20the%20forearm%20is%20the%20flexion%20about%20the%20fixed%20%24%5Cmathbf%7BZ%7D%24%20axis%20composed%20with%20the%20pronation%20about%20the%20forearm's%20own%20axis%2C%20%24%5Cmathbf%7BR%7D(t)%20%3D%20%5Cmathbf%7BR_Z%7D(%5Ctheta_f)%5C%2C%5Cmathbf%7BR%7D_%7B%5Chat%7B%5Cmathbf%7Be%7D%7D_1%7D(%5Ctheta_p)%24%2C%20and%20the%20dot-product%20formula%20needs%20nothing%20else.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20the%20magnitude%20of%20the%20angular%20velocity%20of%20the%20forearm%3A%20%24700%5E%5Ccirc%24%2Fs%2C%20%24500%5E%5Ccirc%24%2Fs%2C%20or%20%24100%5E%5Ccirc%24%2Fs%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_dt%20%3D%201%20%2F%20200%20%20%23%20s%2C%20200%20Hz%0A%20%20%20%20t_forearm%20%3D%20np.arange(0%2C%200.3%20%2B%20_dt%20%2F%202%2C%20_dt)%0A%20%20%20%20_w_flex%2C%20_w_pron%20%3D%20np.radians(300)%2C%20np.radians(400)%20%20%23%20rad%2Fs%0A%0A%20%20%20%20%23%20Flexion%20about%20the%20fixed%20Z%20axis%2C%20pronation%20about%20the%20forearm's%20long%20axis%20(its%20e1)%0A%20%20%20%20_R%20%3D%20np.array(%5Brodrigues(%5B0%2C%200%2C%201%5D%2C%20_w_flex%20*%20_ti)%20%40%20rodrigues(%5B1%2C%200%2C%200%5D%2C%20_w_pron%20*%20_ti)%20for%20_ti%20in%20t_forearm%5D)%0A%20%20%20%20e1_forearm%2C%20_e2%2C%20_e3%20%3D%20_R%5B%3A%2C%20%3A%2C%200%5D%2C%20_R%5B%3A%2C%20%3A%2C%201%5D%2C%20_R%5B%3A%2C%20%3A%2C%202%5D%0A%0A%20%20%20%20_omega_l%20%3D%20angular_velocity(e1_forearm%2C%20_e2%2C%20_e3%2C%20_dt)%0A%20%20%20%20omega_forearm%20%3D%20np.einsum(%22nij%2Cnj-%3Eni%22%2C%20_R%2C%20_omega_l)%20%20%23%20laboratory%20components%0A%20%20%20%20_vector_sum%20%3D%20_w_flex%20*%20np.array(%5B0%2C%200%2C%201%5D)%20%2B%20_w_pron%20*%20e1_forearm%20%20%23%20the%20two%20rotations%2C%20added%20as%20vectors%0A%0A%20%20%20%20_speed%20%3D%20np.degrees(np.linalg.norm(omega_forearm%2C%20axis%3D1))%0A%20%20%20%20_cos%20%3D%20np.sum(omega_forearm%20*%20e1_forearm%2C%20axis%3D1)%20%2F%20np.linalg.norm(omega_forearm%2C%20axis%3D1)%0A%20%20%20%20print(f%22%7Comega%7C%3A%20from%20%7B_speed.min()%3A.1f%7D%20to%20%7B_speed.max()%3A.1f%7D%20deg%2Fs%22)%0A%20%20%20%20print(f%22Largest%20%7Comega%20-%20(flexion%20%2B%20pronation)%7C%3A%20%7Bnp.degrees(np.abs(omega_forearm%20-%20_vector_sum)).max()%3A.2f%7D%20deg%2Fs%22)%0A%20%20%20%20print(f%22Angle%20between%20omega%20and%20the%20forearm's%20long%20axis%3A%20%7Bnp.degrees(np.arccos(_cos)).mean()%3A.1f%7D%20degrees%22)%0A%20%20%20%20print(%22Components%20in%20the%20forearm's%20basis%20at%20t%20%3D%200%20and%20t%20%3D%200.3%20s%20%5Bdeg%2Fs%5D%3A%22)%0A%20%20%20%20print(%22%20%20%22%2C%20np.degrees(_omega_l%5B0%5D).round(1)%2C%20%22%5Cn%20%20%22%2C%20np.degrees(_omega_l%5B-1%5D).round(1))%0A%20%20%20%20return%20(omega_forearm%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%24500%5E%5Ccirc%24%2Fs%2C%20at%20every%20instant.%20The%20two%20angular%20velocities%20add%20as%20vectors%2C%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%3D%20%5Cdot%7B%5Ctheta%7D_f%5C%2C%5Chat%7B%5Cmathbf%7Bk%7D%7D%20%2B%20%5Cdot%7B%5Ctheta%7D_p%5C%2C%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%2C%20to%20within%20%240.4%5E%5Ccirc%24%2Fs%20of%20finite-difference%20error%2C%20and%20since%20the%20elbow's%20axis%20and%20the%20forearm's%20long%20axis%20are%20perpendicular%2C%20the%20magnitudes%20combine%20like%20the%20sides%20of%20a%203-4-5%20triangle%3A%20%24%5Csqrt%7B300%5E2%20%2B%20400%5E2%7D%20%3D%20500%24.%20The%20forearm%20turns%20about%20a%20single%20axis%20at%20each%20instant%2C%20at%20%2436.9%5E%5Ccirc%24%20from%20its%20long%20axis%2C%20an%20axis%20that%20is%20neither%20the%20elbow's%20nor%20the%20forearm's.%0A%0A%20%20%20%20This%20is%20the%20general%20rule.%20If%20body%20B%20turns%20relative%20to%20body%20A%20with%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7BB%2FA%7D%24%2C%20and%20body%20C%20relative%20to%20body%20B%20with%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7BC%2FB%7D%24%2C%20then%20C%20turns%20relative%20to%20A%20with%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7BC%2FA%7D%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7BC%2FB%7D%20%2B%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7BB%2FA%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20whatever%20the%20axes%20(Kane%20and%20Levinson%2C%201985).%20Here%20A%20is%20the%20upper%20arm%2C%20B%20a%20frame%20that%20flexes%20with%20the%20forearm%20but%20does%20not%20pronate%2C%20and%20C%20the%20forearm.%20Read%20backwards%2C%20the%20rule%20gives%20the%20angular%20velocity%20of%20a%20joint%3A%20the%20angular%20velocity%20of%20the%20shank%20relative%20to%20the%20thigh%20is%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7Bshank%7D%20-%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7Bthigh%7D%24%2C%20both%20expressed%20in%20the%20same%20basis.%20No%20such%20rule%20exists%20for%20the%20angles.%0A%0A%20%20%20%20In%20the%20forearm's%20own%20basis%20the%20components%20are%20%24%5B400%2C%200%2C%20300%5D%5E%5Ccirc%24%2Fs%20at%20the%20start%20and%20%24%5B400%2C%20260.2%2C%20-150%5D%5E%5Ccirc%24%2Fs%20at%20the%20end%3A%20the%20pronation%20part%20stays%20along%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%2C%20but%20the%20flexion%20part%2C%20fixed%20to%20the%20upper%20arm%2C%20turns%20relative%20to%20the%20forearm%20as%20the%20forearm%20pronates%20by%20%24120%5E%5Ccirc%24.%0A%0A%20%20%20%20**Exercise%204.**%20The%20magnitude%20of%20the%20forearm's%20angular%20velocity%20is%20constant.%20Is%20its%20direction%20in%20the%20laboratory%20constant%20too%3F%20Find%20the%20angle%20between%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20at%20%24t%20%3D%200%24%20and%20at%20%24t%20%3D%200.3%24%20s%2C%20first%20by%20reasoning%20and%20then%20from%20the%20computed%20%60omega_forearm%60.%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%20omega_forearm)%3A%0A%20%20%20%20_w0%2C%20_w1%20%3D%20omega_forearm%5B0%5D%2C%20omega_forearm%5B-1%5D%0A%20%20%20%20_angle%20%3D%20np.degrees(np.arccos(np.dot(_w0%2C%20_w1)%20%2F%20(np.linalg.norm(_w0)%20*%20np.linalg.norm(_w1))))%0A%20%20%20%20_predicted%20%3D%20np.degrees(np.arccos(300**2%20%2F%20500**2))%0A%0A%20%20%20%20mo.accordion(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Solution%20to%20Exercise%204%22%3A%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rf%22%22%22%0A%20%20%20%20No.%20The%20flexion%20part%2C%20%24300%5E%5Ccirc%24%2Fs%20along%20%24%5Chat%7B%7B%5Cmathbf%7B%7Bk%7D%7D%7D%7D%24%2C%20is%20fixed%20in%20the%20laboratory%2C%20but%20the%20pronation%20part%2C%20%24400%5E%5Ccirc%24%2Fs%20along%20the%20forearm's%20long%20axis%2C%20turns%20with%20the%20forearm%2C%20and%20in%200.3%20s%20the%20flexion%20turns%20the%20long%20axis%20by%20%2490%5E%5Ccirc%24%2C%20from%20%24%5Chat%7B%7B%5Cmathbf%7B%7Bi%7D%7D%7D%7D%24%20to%20%24%5Chat%7B%7B%5Cmathbf%7B%7Bj%7D%7D%7D%7D%24.%20So%20%24%5Cvec%7B%7B%5Cboldsymbol%7B%7B%5Comega%7D%7D%7D%7D(0)%20%3D%20400%5C%2C%5Chat%7B%7B%5Cmathbf%7B%7Bi%7D%7D%7D%7D%20%2B%20300%5C%2C%5Chat%7B%7B%5Cmathbf%7B%7Bk%7D%7D%7D%7D%24%20and%20%24%5Cvec%7B%7B%5Cboldsymbol%7B%7B%5Comega%7D%7D%7D%7D(0.3)%20%3D%20400%5C%2C%5Chat%7B%7B%5Cmathbf%7B%7Bj%7D%7D%7D%7D%20%2B%20300%5C%2C%5Chat%7B%7B%5Cmathbf%7B%7Bk%7D%7D%7D%7D%24%20(in%20degrees%20per%20second)%2C%20and%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Ccos%5Cphi%20%3D%20%5Cfrac%7B%7B%5Cvec%7B%7B%5Cboldsymbol%7B%7B%5Comega%7D%7D%7D%7D(0)%5Ccdot%5Cvec%7B%7B%5Cboldsymbol%7B%7B%5Comega%7D%7D%7D%7D(0.3)%7D%7D%7B%7B500%5E2%7D%7D%20%3D%20%5Cfrac%7B%7B300%5E2%7D%7D%7B%7B500%5E2%7D%7D%20%3D%200.36%0A%20%20%20%20%5Cquad%5CLongrightarrow%5Cquad%20%5Cphi%20%3D%20%7B_predicted%3A.1f%7D%5E%5Ccirc%0A%20%20%20%20%24%24%0A%0A%20%20%20%20From%20the%20computed%20angular%20velocities%2C%20the%20angle%20is%20%24%7B_angle%3A.1f%7D%5E%5Ccirc%24.%20A%20constant-speed%20rotation%20can%20still%20have%20an%20axis%20that%20moves%3A%20the%20angular%20velocity%20changes%2C%20so%20the%20forearm%20has%20an%20angular%20acceleration%20even%20though%20nothing%20speeds%20up.%0A%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Example%3A%20a%203D%20pendulum%20bar%0A%0A%20%20%20%20The%20file%20%603dPendulum.txt%60%2C%20in%20the%20%60data%60%20folder%20of%20this%20repository%2C%20has%203%20seconds%20of%20data%20of%203%20points%20of%20a%20three-dimensional%20cylindrical%20pendulum%2C%20sampled%20at%20100%20Hz.%20The%20pendulum%20can%20move%20in%20every%20direction%20and%20has%20a%20motor%20at%20the%20upper%20part%20of%20the%20cylindrical%20bar%20producing%20torques%20to%20move%20the%20bar.%0A%0A%20%20%20%20-%20The%20point%20m1%20is%20at%20the%20upper%20part%20of%20the%20cylinder%20and%20is%20the%20origin%20of%20the%20system.%0A%20%20%20%20-%20The%20point%20m2%20is%20at%20the%20center%20of%20mass%20of%20the%20cylinder.%0A%20%20%20%20-%20The%20point%20m3%20is%20a%20point%20at%20the%20surface%20of%20the%20cylinder.%0A%0A%20%20%20%20Below%20we%20compute%20its%20angular%20velocity.%20First%20we%20load%20the%20file%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20repo_file)%3A%0A%20%20%20%20np.set_printoptions(precision%3D4%2C%20suppress%3DTrue)%0A%0A%20%20%20%20data%20%3D%20np.loadtxt(repo_file(%22data%2F3dPendulum.txt%22)%2C%20skiprows%3D1%2C%20delimiter%3D%22%2C%22)%0A%20%20%20%20return%20(data%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%20And%20separate%20each%20marker%20in%20a%20variable%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(data)%3A%0A%20%20%20%20t%20%3D%20data%5B%3A%2C%200%5D%0A%20%20%20%20m1%20%3D%20data%5B%3A%2C%201%3A4%5D%0A%20%20%20%20m2%20%3D%20data%5B%3A%2C%204%3A7%5D%0A%20%20%20%20m3%20%3D%20data%5B%3A%2C%207%3A%5D%0A%20%20%20%20dt%20%3D%20t%5B1%5D%0A%20%20%20%20return%20dt%2C%20m1%2C%20m2%2C%20m3%2C%20t%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%20we%20form%20the%20basis%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_1%24%2C%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_2%24%20and%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_3%24.%20The%20first%20versor%20is%20along%20the%20bar%2C%20from%20the%20top%20to%20the%20center%20of%20mass%3B%20the%20second%20is%20perpendicular%20to%20the%20plane%20of%20the%20three%20points%3B%20the%20third%20completes%20a%20right-handed%20basis%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(m1%2C%20m2%2C%20m3%2C%20np)%3A%0A%20%20%20%20V1%20%3D%20m2%20-%20m1%0A%20%20%20%20e1%20%3D%20V1%20%2F%20np.linalg.norm(V1%2C%20axis%3D1%2C%20keepdims%3DTrue)%0A%0A%20%20%20%20V2%20%3D%20m3%20-%20m2%0A%0A%20%20%20%20V3%20%3D%20np.cross(V2%2C%20V1)%0A%20%20%20%20e2%20%3D%20V3%20%2F%20np.linalg.norm(V3%2C%20axis%3D1%2C%20keepdims%3DTrue)%0A%0A%20%20%20%20e3%20%3D%20np.cross(e1%2C%20e2)%0A%20%20%20%20return%20e1%2C%20e2%2C%20e3%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%20Below%2C%20we%20compute%20the%20derivative%20of%20each%20of%20the%20versors%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(dt%2C%20e1%2C%20e2%2C%20e3%2C%20np)%3A%0A%20%20%20%20de1dt%20%3D%20np.gradient(e1%2C%20dt%2C%20axis%3D0%2C%20edge_order%3D2)%0A%20%20%20%20de2dt%20%3D%20np.gradient(e2%2C%20dt%2C%20axis%3D0%2C%20edge_order%3D2)%0A%20%20%20%20de3dt%20%3D%20np.gradient(e3%2C%20dt%2C%20axis%3D0%2C%20edge_order%3D2)%0A%20%20%20%20return%20de1dt%2C%20de2dt%2C%20de3dt%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%20we%20compute%20each%20of%20the%20components%20%24%5Comega_1%24%2C%20%24%5Comega_2%24%20and%20%24%5Comega_3%24%20of%20the%20angular%20velocity%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20by%20using%20the%20scalar%20product%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(de1dt%2C%20de2dt%2C%20de3dt%2C%20e1%2C%20e2%2C%20e3%2C%20np)%3A%0A%20%20%20%20omega1%20%3D%20np.sum(de2dt%20*%20e3%2C%20axis%3D1%2C%20keepdims%3DTrue)%0A%20%20%20%20omega2%20%3D%20np.sum(de3dt%20*%20e1%2C%20axis%3D1%2C%20keepdims%3DTrue)%0A%20%20%20%20omega3%20%3D%20np.sum(de1dt%20*%20e2%2C%20axis%3D1%2C%20keepdims%3DTrue)%0A%20%20%20%20return%20omega1%2C%20omega2%2C%20omega3%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%20Finally%2C%20the%20angular%20velocity%20vector%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20is%20formed%20by%20stacking%20the%20three%20components%20together.%20The%20function%20%60angular_velocity%60%20does%20the%20same%20three%20steps%2C%20and%20must%20agree%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(dt%2C%20e1%2C%20e2%2C%20e3%2C%20np%2C%20omega1%2C%20omega2%2C%20omega3)%3A%0A%20%20%20%20omega%20%3D%20np.hstack((omega1%2C%20omega2%2C%20omega3))%0A%0A%20%20%20%20print(%22Same%20as%20angular_velocity()%3F%22%2C%20np.allclose(omega%2C%20angular_velocity(e1%2C%20e2%2C%20e3%2C%20dt)))%0A%20%20%20%20return%20(omega%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**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20the%20pendulum%20can%20move%20in%20every%20direction%2C%20and%20its%20motor%20can%20push%20it%20any%20way.%20Which%20of%20the%20three%20components%20of%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20will%20you%20see%20changing%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(e1%2C%20e2%2C%20np%2C%20omega%2C%20plt%2C%20t)%3A%0A%20%20%20%20_R%20%3D%20np.stack((e1%2C%20e2%2C%20np.cross(e1%2C%20e2))%2C%20axis%3D2)%20%20%23%20versors%20in%20the%20columns%0A%20%20%20%20omega_G%20%3D%20np.einsum(%22nij%2Cnj-%3Eni%22%2C%20_R%2C%20omega)%0A%20%20%20%20bar_angle%20%3D%20np.degrees(np.arccos(np.clip(-e1%5B%3A%2C%202%5D%2C%20-1%2C%201)))%20%20%23%20the%20bar%20hangs%20along%20-Z%0A%0A%20%20%20%20print(%22Range%20of%20each%20body%20component%20%5Brad%2Fs%5D%3A%22)%0A%20%20%20%20for%20_name%2C%20_col%20in%20zip(%5B%22omega_1%22%2C%20%22omega_2%22%2C%20%22omega_3%22%5D%2C%20omega.T)%3A%0A%20%20%20%20%20%20%20%20print(f%22%20%20%7B_name%7D%3A%20from%20%7B_col.min()%3A8.4f%7D%20to%20%7B_col.max()%3A8.4f%7D%22)%0A%20%20%20%20_moving%20%3D%20np.linalg.norm(omega_G%2C%20axis%3D1)%20%3E%201e-3%0A%20%20%20%20_dirs%20%3D%20omega_G%5B_moving%5D%20%2F%20np.linalg.norm(omega_G%5B_moving%5D%2C%20axis%3D1%2C%20keepdims%3DTrue)%0A%20%20%20%20_dirs%20%3D%20_dirs%20*%20np.sign(_dirs%5B%3A%2C%20%3A1%5D)%0A%20%20%20%20print(%22Direction%20of%20omega%20in%20the%20laboratory%3A%20from%22%2C%20_dirs.min(axis%3D0).round(4)%2C%20%22to%22%2C%20_dirs.max(axis%3D0).round(4))%0A%20%20%20%20print(f%22Angle%20of%20the%20bar%20from%20the%20vertical%3A%20from%20%7Bbar_angle.min()%3A.1f%7D%20to%20%7Bbar_angle.max()%3A.1f%7D%20degrees%22)%0A%0A%20%20%20%20_%2C%20_axs%20%3D%20plt.subplots(2%2C%201%2C%20figsize%3D(9%2C%206)%2C%20sharex%3DTrue)%0A%20%20%20%20for%20_i%2C%20(_label%2C%20_color)%20in%20enumerate(%0A%20%20%20%20%20%20%20%20zip(%5Br%22%24%5Comega_1%24%22%2C%20r%22%24%5Comega_2%24%22%2C%20r%22%24%5Comega_3%24%22%5D%2C%20%5B%22tab%3Ared%22%2C%20%22tab%3Agreen%22%2C%20%22tab%3Ablue%22%5D)%0A%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20_axs%5B0%5D.plot(t%2C%20omega%5B%3A%2C%20_i%5D%2C%20color%3D_color%2C%20linewidth%3D2%2C%20label%3D_label)%0A%20%20%20%20_axs%5B0%5D.set_ylabel(%22Angular%20velocity%20%5Brad%2Fs%5D%22)%0A%20%20%20%20_axs%5B0%5D.set_title(%22Pendulum%20bar%2C%20components%20in%20its%20own%20basis%22)%0A%20%20%20%20_axs%5B0%5D.legend(loc%3D%22lower%20right%22%2C%20ncol%3D3)%0A%20%20%20%20_axs%5B1%5D.plot(t%2C%20bar_angle%2C%20color%3D%22k%22%2C%20linewidth%3D2)%0A%20%20%20%20_axs%5B1%5D.set_ylabel(%22Angle%20from%20vertical%20%5Bdeg%5D%22)%0A%20%20%20%20_axs%5B1%5D.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20bar_angle%2C%20omega_G%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%20Only%20%24%5Comega_2%24%20changes.%20The%20spin%20about%20the%20bar's%20long%20axis%2C%20%24%5Comega_1%24%2C%20and%20%24%5Comega_3%24%20are%20zero%20to%20within%20%2410%5E%7B-14%7D%24%20rad%2Fs%20(their%20two%20lines%20lie%20on%20top%20of%20each%20other).%20In%20the%20laboratory%2C%20the%20angular%20velocity%20always%20points%20along%20the%20same%20horizontal%20line%2C%20%24%5Cpm%5B0.5%2C%20-0.866%2C%200%5D%24%3A%20in%20these%20three%20seconds%20the%20bar%20swings%20in%20a%20single%20vertical%20plane%2C%20between%20%2415.3%5E%5Ccirc%24%20and%20%2420.8%5E%5Ccirc%24%20from%20the%20vertical%2C%20with%20%24%5Comega_2%24%20reaching%20%240.31%24%20rad%2Fs%20(%2417.7%5E%5Ccirc%24%2Fs).%20The%20motor's%20torques%20show%20up%20as%20a%20swing%20that%20changes%20direction%20at%20irregular%20intervals.%0A%0A%20%20%20%20The%20pendulum%20*could*%20have%20moved%20in%203D%3B%20it%20did%20not%2C%20and%20the%20formula%20found%20that%20out%20without%20being%20told.%20That%20is%20the%20kind%20of%20result%20to%20look%20for%20before%20drawing%20conclusions%20from%203D%20data%3A%20a%20planar%20motion%20described%20with%20three%20components.%0A%0A%20%20%20%20%23%23%23%20Checking%20with%20the%20velocity%20of%20a%20point%0A%0A%20%20%20%20The%20angular%20velocity%20predicts%20the%20velocity%20of%20every%20point%20of%20the%20bar.%20The%20top%2C%20m1%2C%20does%20not%20move%2C%20so%20for%20the%20point%20m3%2C%20%24%5Cvec%7B%5Cmathbf%7Bv%7D%7D_%7Bm3%7D%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20(%5Cvec%7B%5Cmathbf%7Br%7D%7D_%7Bm3%7D%20-%20%5Cvec%7B%5Cmathbf%7Br%7D%7D_%7Bm1%7D)%24%2C%20as%20in%20%5BKinematics%20of%20a%20rigid%20body%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_of_rigid_body.py).%20The%20prediction%20can%20be%20compared%20with%20the%20velocity%20of%20m3%20differentiated%20directly%20from%20its%20positions%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(dt%2C%20m1%2C%20m2%2C%20m3%2C%20np%2C%20omega_G)%3A%0A%20%20%20%20_v3%20%3D%20np.gradient(m3%2C%20dt%2C%20axis%3D0%2C%20edge_order%3D2)%0A%20%20%20%20_v3_pred%20%3D%20np.cross(omega_G%2C%20m3%20-%20m1)%0A%0A%20%20%20%20print(f%22Largest%20speed%20of%20m3%3A%20%7Bnp.linalg.norm(_v3%2C%20axis%3D1).max()%3A.4f%7D%20m%2Fs%22)%0A%20%20%20%20print(f%22Largest%20%7Cv_m3%20-%20omega%20x%20r%7C%3A%20%7Bnp.abs(_v3%20-%20_v3_pred).max()%3A.1e%7D%20m%2Fs%22)%0A%20%20%20%20for%20_a%2C%20_b%2C%20_name%20in%20%5B(m1%2C%20m2%2C%20%22m1-m2%22)%2C%20(m1%2C%20m3%2C%20%22m1-m3%22)%2C%20(m2%2C%20m3%2C%20%22m2-m3%22)%5D%3A%0A%20%20%20%20%20%20%20%20_d%20%3D%20np.linalg.norm(_b%20-%20_a%2C%20axis%3D1)%0A%20%20%20%20%20%20%20%20print(f%22Distance%20%7B_name%7D%3A%20from%20%7B_d.min()%3A.4f%7D%20to%20%7B_d.max()%3A.4f%7D%20m%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20prediction%20matches%20to%20within%20%241.5%20%5Ctimes%2010%5E%7B-5%7D%24%20m%2Fs%2C%20for%20a%20point%20that%20moves%20at%20up%20to%20%240.16%24%20m%2Fs%2C%20and%20the%20distances%20between%20the%20three%20points%20are%20constant.%20The%20bar%20is%20a%20perfect%20rigid%20body%2C%20as%20befits%20data%20that%20come%20from%20a%20simulation.%20Real%20markers%20on%20a%20real%20segment%20will%20be%20less%20obliging.%0A%0A%20%20%20%20**Exercise%205.**%20In%20a%20plane%2C%20integrating%20the%20angular%20velocity%20over%20time%20gives%20the%20angle%20turned.%20Integrate%20%24%5Comega_2%24%20of%20the%20pendulum%20(for%20example%20with%20%60scipy.integrate.cumulative_trapezoid%60)%20and%20compare%20the%20result%20with%20the%20change%20of%20the%20bar's%20angle%20from%20the%20vertical%2C%20%60bar_angle%60.%20Do%20they%20agree%3F%20Would%20the%20same%20work%20for%20the%20components%20of%20a%20genuinely%203D%20motion%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(bar_angle%2C%20mo%2C%20np%2C%20omega%2C%20t)%3A%0A%20%20%20%20from%20scipy.integrate%20import%20cumulative_trapezoid%0A%0A%20%20%20%20_turned%20%3D%20np.degrees(cumulative_trapezoid(omega%5B%3A%2C%201%5D%2C%20t%2C%20initial%3D0))%0A%20%20%20%20_change%20%3D%20bar_angle%20-%20bar_angle%5B0%5D%0A%20%20%20%20_mismatch%20%3D%20np.abs(_turned%20%2B%20_change).max()%0A%0A%20%20%20%20mo.accordion(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Solution%20to%20Exercise%205%22%3A%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rf%22%22%22%0A%20%20%20%20The%20integral%20of%20%24%5Comega_2%24%20goes%20from%20%24%7B_turned.min()%3A.2f%7D%5E%5Ccirc%24%20to%20%24%7B_turned.max()%3A.2f%7D%5E%5Ccirc%24%2C%20and%20the%20change%20of%20the%20bar's%20angle%20from%20the%20vertical%20from%20%24%7B_change.min()%3A.2f%7D%5E%5Ccirc%24%20to%20%24%7B_change.max()%3A.2f%7D%5E%5Ccirc%24.%20They%20agree%20to%20within%20%24%7B_mismatch%3A.3f%7D%5E%5Ccirc%24%20at%20every%20instant%2C%20with%20opposite%20signs%3A%20with%20the%20direction%20chosen%20for%20%24%5Chat%7B%7B%5Cmathbf%7B%7Be%7D%7D%7D%7D_2%24%2C%20a%20positive%20%24%5Comega_2%24%20swings%20the%20bar%20back%20towards%20the%20vertical.%0A%0A%20%20%20%20It%20works%20here%20because%20the%20axis%20of%20rotation%20is%20fixed%3A%20%24%5Chat%7B%7B%5Cmathbf%7B%7Be%7D%7D%7D%7D_2%24%20points%20along%20the%20same%20line%20throughout%2C%20and%20a%20rotation%20about%20a%20fixed%20axis%20is%20a%20planar%20rotation.%20For%20a%20genuinely%203D%20motion%2C%20the%20integral%20of%20each%20component%20of%20%24%5Cvec%7B%7B%5Cboldsymbol%7B%7B%5Comega%7D%7D%7D%7D%24%20is%20not%20an%20angle%20of%20anything%3A%20it%20would%20be%20adding%20up%20small%20rotations%20about%20axes%20that%20keep%20moving%2C%20and%20finite%20rotations%2C%20as%20we%20saw%2C%20do%20not%20add%20like%20vectors.%20The%20orientation%20has%20to%20be%20obtained%20by%20composing%20the%20small%20rotations%2C%20not%20by%20summing%20their%20components.%0A%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Back%20to%20the%20shank%0A%0A%20%20%20%20Now%20the%20question%20we%20started%20with.%20The%20file%20%60walk.trc%60%2C%20in%20the%20%60data%60%20folder%20of%20this%20repository%2C%20is%20the%20walking%20trial%20used%20in%20%5BRigid-body%20transformations%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_3d.py)%2C%20with%20the%20laboratory's%20%24%5Cmathbf%7BX%7D%24%20axis%20pointing%20forward%2C%20%24%5Cmathbf%7BY%7D%24%20upwards%20and%20%24%5Cmathbf%7BZ%7D%24%20to%20the%20right.%20We%20build%20the%20basis%20of%20the%20right%20shank%20exactly%20as%20there%3A%20%24y%24%20from%20the%20ankle%20to%20the%20knee%20joint%20center%2C%20%24x%24%20perpendicular%20to%20%24y%24%20and%20to%20the%20line%20through%20the%20malleoli%20(lateral%20minus%20medial%2C%20for%20the%20right%20leg)%2C%20and%20%24z%20%3D%20x%20%5Ctimes%20y%24.%0A%0A%20%20%20%20One%20detail%20matters%20here%20more%20than%20it%20did%20there.%20The%20%60Time%60%20column%20of%20the%20file%20is%20rounded%20to%20the%20millisecond%2C%20so%20the%20difference%20between%20its%20first%20two%20values%20is%200.007%20s%2C%20while%20the%20true%20interval%20at%20150%20Hz%20is%200.00667%20s.%20Used%20for%20the%20derivatives%2C%20that%20difference%20would%20inflate%20every%20angular%20velocity%20by%205%25.%20The%20sampling%20rate%20in%20the%20header%20is%20the%20reliable%20number%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20read_trc%2C%20repo_file)%3A%0A%20%20%20%20_h%2C%20_walk%20%3D%20read_trc(str(repo_file(%22data%2Fwalk.trc%22))%2C%20fmt%3D%22uni%22%2C%20show_msg%3DFalse)%0A%20%20%20%20t_walk%20%3D%20_walk%5B%22Time%22%5D.to_numpy()%0A%20%20%20%20dt_walk%20%3D%201%20%2F%20_h%5B%22data_rate%22%5D%0A%20%20%20%20print(f%22First%20time%20stamps%3A%20%7Bt_walk%5B%3A4%5D%7D%20s%3B%20header%3A%20%7B_h%5B'data_rate'%5D%3A.0f%7D%20Hz%2C%20dt%20%3D%20%7Bdt_walk%3A.5f%7D%20s%22)%0A%0A%20%20%20%20def%20_marker(name)%3A%0A%20%20%20%20%20%20%20%20return%20_walk%5B%5Bname%20%2B%20c%20for%20c%20in%20%22xyz%22%5D%5D.to_numpy()%20%2F%2010%20%20%23%20cm%0A%0A%20%20%20%20_lm%2C%20_mm%20%3D%20_marker(%22R.Ankle%22)%2C%20_marker(%22R.Ankle.Medial%22)%0A%20%20%20%20_fh%2C%20_mc%20%3D%20_marker(%22R.HF%22)%2C%20_marker(%22R.Knee.Medial%22)%0A%20%20%20%20ajc%2C%20kjc%20%3D%20(_lm%20%2B%20_mm)%20%2F%202%2C%20(_fh%20%2B%20_mc)%20%2F%202%20%20%23%20ankle%20and%20knee%20joint%20centers%0A%0A%20%20%20%20_y%20%3D%20kjc%20-%20ajc%0A%20%20%20%20_x%20%3D%20np.cross(_y%2C%20_lm%20-%20_mm)%20%20%23%20lateral%20minus%20medial%3A%20right%20leg%2C%20Z%20to%20the%20right%0A%20%20%20%20_z%20%3D%20np.cross(_x%2C%20_y)%0A%20%20%20%20x_shank%2C%20y_shank%2C%20z_shank%20%3D%20(_v%20%2F%20np.linalg.norm(_v%2C%20axis%3D1%2C%20keepdims%3DTrue)%20for%20_v%20in%20(_x%2C%20_y%2C%20_z))%0A%20%20%20%20R_lG%20%3D%20np.stack((x_shank%2C%20y_shank%2C%20z_shank)%2C%20axis%3D1)%20%20%23%20versors%20in%20the%20rows%0A%20%20%20%20return%20R_lG%2C%20ajc%2C%20dt_walk%2C%20kjc%2C%20t_walk%2C%20x_shank%2C%20y_shank%2C%20z_shank%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%20Cardan%20angles%20in%20the%20%24xyz%24%20sequence%20come%20from%20the%20rotation%20matrix%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%20(the%20versors%20in%20its%20rows)%20with%20the%20formulas%20of%20Rigid-body%20transformations%20in%203D%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20cardan_xyz(R_lG)%3A%0A%20%20%20%20%22%22%22Cardan%20angles%20%5Balpha%2C%20beta%2C%20gamma%5D%20in%20radians%2C%20xyz%20sequence%2C%20from%20R_lG%20(versors%20as%20rows).%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20R%20%3D%20np.asarray(R_lG%2C%20dtype%3Dfloat)%0A%20%20%20%20alpha%20%3D%20np.arctan2(-R%5B2%2C%201%5D%2C%20R%5B2%2C%202%5D)%0A%20%20%20%20beta%20%3D%20np.arctan2(R%5B2%2C%200%5D%2C%20np.sqrt(R%5B0%2C%200%5D%20**%202%20%2B%20R%5B1%2C%200%5D%20**%202))%0A%20%20%20%20gamma%20%3D%20np.arctan2(-R%5B1%2C%200%5D%2C%20R%5B0%2C%200%5D)%0A%20%20%20%20return%20np.array(%5Balpha%2C%20beta%2C%20gamma%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%20Now%20the%20two%20candidates%20for%20the%20angular%20velocity%20of%20the%20shank%3A%20the%20derivatives%20of%20the%20three%20Cardan%20angles%2C%20and%20the%20components%20of%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20in%20the%20shank's%20own%20basis%20from%20the%20dot-product%20formula%2C%20about%20its%20%24x%24%2C%20%24y%24%20and%20%24z%24%20axes.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20go%20back%20to%20Guiding%20question%200.1%20and%20commit%20to%20an%20answer%3A%20will%20the%20two%20agree%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R_lG%2C%20dt_walk%2C%20np%2C%20plt%2C%20t_walk%2C%20x_shank%2C%20y_shank%2C%20z_shank)%3A%0A%20%20%20%20angles_shank%20%3D%20np.array(%5Bcardan_xyz(_R)%20for%20_R%20in%20R_lG%5D)%0A%20%20%20%20rates_shank%20%3D%20np.gradient(np.unwrap(angles_shank%2C%20axis%3D0)%2C%20dt_walk%2C%20axis%3D0%2C%20edge_order%3D2)%0A%20%20%20%20omega_shank%20%3D%20angular_velocity(x_shank%2C%20y_shank%2C%20z_shank%2C%20dt_walk)%0A%0A%20%20%20%20_deg%20%3D%20np.degrees%0A%20%20%20%20_speed%20%3D%20np.linalg.norm(omega_shank%2C%20axis%3D1)%0A%20%20%20%20_i%20%3D%20np.argmax(_speed)%0A%20%20%20%20_j%20%3D%20np.argmax(np.abs(rates_shank%5B%3A%2C%202%5D))%0A%20%20%20%20print(f%22Peak%20%7Comega%7C%3A%20%7B_deg(_speed%5B_i%5D)%3A.0f%7D%20deg%2Fs%20at%20t%20%3D%20%7Bt_walk%5B_i%5D%3A.3f%7D%20s%22)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22Peak%20d(gamma)%2Fdt%3A%20%7B_deg(rates_shank%5B_j%2C%202%5D)%3A.0f%7D%20deg%2Fs%20at%20t%20%3D%20%7Bt_walk%5B_j%5D%3A.3f%7D%20s%2C%22%0A%20%20%20%20%20%20%20%20f%22%20where%20omega_z%20%3D%20%7B_deg(omega_shank%5B_j%2C%202%5D)%3A.0f%7D%20deg%2Fs%20and%20%7Comega%7C%20%3D%20%7B_deg(_speed%5B_j%5D)%3A.0f%7D%20deg%2Fs%22%0A%20%20%20%20)%0A%20%20%20%20print(%22Largest%20%7Comega%20-%20angle%20rate%7C%20for%20x%2Falpha%2C%20y%2Fbeta%2C%20z%2Fgamma%20%5Bdeg%2Fs%5D%3A%22%2C%20np.abs(_deg(omega_shank%20-%20rates_shank)).max(axis%3D0).round(0))%0A%0A%20%20%20%20_%2C%20_axs%20%3D%20plt.subplots(3%2C%201%2C%20figsize%3D(9%2C%208)%2C%20sharex%3DTrue)%0A%20%20%20%20_pairs%20%3D%20%5B(%22x%22%2C%20r%22%5Calpha%22)%2C%20(%22y%22%2C%20r%22%5Cbeta%22)%2C%20(%22z%22%2C%20r%22%5Cgamma%22)%5D%0A%20%20%20%20for%20_k%2C%20((_axis%2C%20_angle)%2C%20_color)%20in%20enumerate(zip(_pairs%2C%20%5B%22tab%3Ared%22%2C%20%22tab%3Agreen%22%2C%20%22tab%3Ablue%22%5D))%3A%0A%20%20%20%20%20%20%20%20_axs%5B_k%5D.plot(t_walk%2C%20_deg(omega_shank%5B%3A%2C%20_k%5D)%2C%20color%3D_color%2C%20linewidth%3D2%2C%20label%3Drf%22%24%5Comega_%7B_axis%7D%24%22)%0A%20%20%20%20%20%20%20%20_axs%5B_k%5D.plot(t_walk%2C%20_deg(rates_shank%5B%3A%2C%20_k%5D)%2C%20color%3D%22k%22%2C%20linewidth%3D1.5%2C%20linestyle%3D%22--%22%2C%20label%3Drf%22%24d%7B_angle%7D%2Fdt%24%22)%0A%20%20%20%20%20%20%20%20_axs%5B_k%5D.set_ylabel(%22%5Bdeg%2Fs%5D%22)%0A%20%20%20%20%20%20%20%20_axs%5B_k%5D.legend(loc%3D%22upper%20right%22%2C%20ncol%3D2)%0A%20%20%20%20_axs%5B0%5D.set_title(%22Right%20shank%3A%20angular%20velocity%20(shank's%20basis)%20vs.%20Cardan%20angle%20rates%22)%0A%20%20%20%20_axs%5B2%5D.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20angles_shank%2C%20omega_shank%2C%20rates_shank%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%20They%20do%20not%20agree.%20The%20derivative%20of%20%24%5Cgamma%24%20peaks%20at%20%24379%5E%5Ccirc%24%2Fs%20in%20late%20swing%2C%20but%20at%20that%20instant%20the%20angular%20velocity%20of%20the%20shank%20about%20its%20own%20%24z%24%20axis%20is%20%24305%5E%5Ccirc%24%2Fs%2C%20and%20its%20magnitude%2C%20the%20actual%20rate%20at%20which%20the%20shank%20turns%2C%20is%20%24329%5E%5Ccirc%24%2Fs.%20The%20fastest%20the%20shank%20turns%20during%20the%20whole%20trial%20is%20%24330%5E%5Ccirc%24%2Fs.%20Component%20by%20component%2C%20the%20angle%20rates%20differ%20from%20the%20angular%20velocity%20by%20up%20to%20%2492%24%2C%20%24119%24%20and%20%2496%5E%5Ccirc%24%2Fs.%20(The%20spikes%20at%20the%20very%20last%20samples%20are%20edge%20effects%3A%20there%20the%20derivatives%20can%20only%20use%20samples%20on%20one%20side%2C%20and%20the%20markers%20are%20noisy.)%0A%0A%20%20%20%20Nothing%20is%20wrong%20with%20either%20calculation.%20The%20angle%20rates%20are%20rates%20of%20change%20of%20three%20*finite*%20rotations%20about%20axes%20that%20are%20themselves%20moving%2C%20and%20finite%20rotations%2C%20as%20we%20saw%2C%20are%20not%20vectors.%20Only%20the%20angular%20velocity%20is.%0A%0A%20%20%20%20%23%23%23%20From%20angle%20rates%20to%20angular%20velocity%0A%0A%20%20%20%20The%20two%20are%20related%2C%20and%20the%20relation%20can%20be%20derived%20from%20the%20rotation%20matrix%20of%20the%20%24xyz%24%20sequence%2C%20%24%5Cmathbf%7BR_%7BlG%7D%7D%20%3D%20%5Cmathbf%7BR_z%7D(%5Cgamma)%5C%2C%5Cmathbf%7BR_y%7D(%5Cbeta)%5C%2C%5Cmathbf%7BR_x%7D(%5Calpha)%24%2C%20with%20the%20elemental%20matrices%20of%20the%20local%20(rotating)%20axes.%20With%20the%20versors%20in%20the%20rows%20of%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%2C%20the%20element%20in%20row%20%24i%24%20and%20column%20%24j%24%20of%20%24%5Cdot%7B%5Cmathbf%7BR%7D%7D_%7BlG%7D%5Cmathbf%7BR_%7BlG%7D%7D%5ET%24%20is%20%24%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_i%7D%7Bdt%7D%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_j%24%2C%20so%20the%20dot-product%20formula%20picks%20three%20of%20its%20elements.%20Differentiating%20with%20the%20chain%20rule%2C%20SymPy%20does%20the%20rest%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo%2C%20sym)%3A%0A%20%20%20%20_a%2C%20_b%2C%20_g%20%3D%20sym.symbols(%22alpha%20beta%20gamma%22)%0A%20%20%20%20_ad%2C%20_bd%2C%20_gd%20%3D%20sym.symbols(r%22%5Cdot%7B%5Calpha%7D%20%5Cdot%7B%5Cbeta%7D%20%5Cdot%7B%5Cgamma%7D%22)%0A%20%20%20%20_c%2C%20_s%20%3D%20sym.cos%2C%20sym.sin%0A%0A%20%20%20%20%23%20Elemental%20rotation%20matrices%20of%20the%20local%20(rotating)%20axes%3A%0A%20%20%20%20_Rx%20%3D%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20_c(_a)%2C%20_s(_a)%5D%2C%20%5B0%2C%20-_s(_a)%2C%20_c(_a)%5D%5D)%0A%20%20%20%20_Ry%20%3D%20sym.Matrix(%5B%5B_c(_b)%2C%200%2C%20-_s(_b)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B_s(_b)%2C%200%2C%20_c(_b)%5D%5D)%0A%20%20%20%20_Rz%20%3D%20sym.Matrix(%5B%5B_c(_g)%2C%20_s(_g)%2C%200%5D%2C%20%5B-_s(_g)%2C%20_c(_g)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%20%20%20%20_R%20%3D%20_Rz%20*%20_Ry%20*%20_Rx%20%20%23%20R_lG%20for%20the%20xyz%20sequence%0A%0A%20%20%20%20_Rdot%20%3D%20_R.diff(_a)%20*%20_ad%20%2B%20_R.diff(_b)%20*%20_bd%20%2B%20_R.diff(_g)%20*%20_gd%0A%20%20%20%20_W%20%3D%20sym.simplify(_Rdot%20*%20_R.T)%0A%20%20%20%20_omega%20%3D%20sym.Matrix(%5B_W%5B1%2C%202%5D%2C%20_W%5B2%2C%200%5D%2C%20_W%5B0%2C%201%5D%5D)%20%20%23%20(de2.e3%2C%20de3.e1%2C%20de1.e2)%0A%20%20%20%20E%20%3D%20sym.simplify(_omega.jacobian(%5B_ad%2C%20_bd%2C%20_gd%5D))%0A%20%20%20%20E_func%20%3D%20sym.lambdify((_a%2C%20_b%2C%20_g)%2C%20E%2C%20%22numpy%22)%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20rf%22%22%22%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbegin%7B%7Bbmatrix%7D%7D%5Comega_x%5C%5C%20%5Comega_y%5C%5C%20%5Comega_z%5Cend%7B%7Bbmatrix%7D%7D%20%3D%20%7Bsym.latex(E)%7D%0A%20%20%20%20%5Cbegin%7B%7Bbmatrix%7D%7D%5Cdot%7B%7B%5Calpha%7D%7D%5C%5C%20%5Cdot%7B%7B%5Cbeta%7D%7D%5C%5C%20%5Cdot%7B%7B%5Cgamma%7D%7D%5Cend%7B%7Bbmatrix%7D%7D%2C%0A%20%20%20%20%5Cqquad%20%5Cdet%20%5Cmathbf%7B%7BE%7D%7D%20%3D%20%7Bsym.latex(sym.simplify(E.det()))%7D%0A%20%20%20%20%24%24%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%20(E_func%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%20matrix%20%24%5Cmathbf%7BE%7D%24%20is%20the%20identity%20only%20when%20%24%5Cbeta%20%3D%20%5Cgamma%20%3D%200%24%3B%20otherwise%20each%20component%20of%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20mixes%20several%20angle%20rates.%20The%20last%20row%2C%20for%20instance%2C%20says%20%24%5Comega_z%20%3D%20%5Csin%5Cbeta%5C%3B%5Cdot%7B%5Calpha%7D%20%2B%20%5Cdot%7B%5Cgamma%7D%24%3A%20with%20the%20shank%20turned%20by%20about%20%24-30%5E%5Ccirc%24%20about%20its%20long%20axis%2C%20the%20derivative%20of%20%24%5Cgamma%24%20overstates%20the%20rotation%20about%20%24z%24%20by%20half%20of%20%24%5Cdot%7B%5Calpha%7D%24%2C%20which%20is%20exactly%20what%20happened%20in%20late%20swing.%20And%20%24%5Cdet%5Cmathbf%7BE%7D%20%3D%20%5Ccos%5Cbeta%24%20vanishes%20at%20%24%5Cbeta%20%3D%20%5Cpm%2090%5E%5Ccirc%24%3A%20at%20gimbal%20lock%20no%20set%20of%20finite%20angle%20rates%20can%20represent%20some%20angular%20velocities%2C%20the%20same%20singularity%20seen%20in%20Rigid-body%20transformations%20in%203D.%0A%0A%20%20%20%20Let's%20check%20that%20%24%5Cmathbf%7BE%7D%24%20times%20the%20measured%20angle%20rates%20gives%20back%20the%20angular%20velocity%20from%20the%20versors%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(E_func%2C%20angles_shank%2C%20np%2C%20omega_shank%2C%20rates_shank)%3A%0A%20%20%20%20_omega_from_rates%20%3D%20np.array(%5Bnp.asarray(E_func(*_ang)%2C%20dtype%3Dfloat)%20%40%20_r%20for%20_ang%2C%20_r%20in%20zip(angles_shank%2C%20rates_shank)%5D)%0A%0A%20%20%20%20print(f%22Largest%20%7CE%20(angle%20rates)%20-%20omega%7C%3A%20%7Bnp.degrees(np.abs(_omega_from_rates%20-%20omega_shank)).max()%3A.1f%7D%20deg%2Fs%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%20Within%20%242.2%5E%5Ccirc%24%2Fs%2C%20against%20values%20of%20up%20to%20%24330%5E%5Ccirc%24%2Fs%3B%20the%20small%20difference%20comes%20from%20differentiating%20two%20different%20nonlinear%20functions%20of%20the%20same%20noisy%20markers.%20Angle%20rates%20and%20angular%20velocity%20carry%20the%20same%20information%2C%20but%20only%20the%20angular%20velocity%20can%20be%20used%20directly%20in%20mechanics%3A%20in%20%24%5Cvec%7B%5Cmathbf%7Bv%7D%7D%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20%5Cvec%7B%5Cmathbf%7Br%7D%7D%24%2C%20in%20the%20angular%20momentum%2C%20in%20the%20kinetic%20energy%20of%20rotation%20(see%20%5BKinetics%20of%20a%203D%20rigid%20body%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinetics_3d_rigid_body.py)).%0A%0A%20%20%20%20%23%23%23%20Where%20the%20shank's%20angular%20velocity%20points%0A%0A%20%20%20%20In%20the%20laboratory's%20basis%2C%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_G%20%3D%20%5Cmathbf%7BR_%7BlG%7D%7D%5ET%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_l%24%20(the%20versors%20are%20in%20the%20rows%20of%20%24%5Cmathbf%7BR_%7BlG%7D%7D%24%2C%20so%20its%20transpose%20has%20them%20in%20the%20columns).%20And%20the%20rigid-body%20prediction%20can%20be%20checked%20once%20more%2C%20with%20the%20velocity%20of%20the%20knee%20joint%20center%20relative%20to%20the%20ankle%20joint%20center%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R_lG%2C%20ajc%2C%20dt_walk%2C%20kjc%2C%20np%2C%20omega_shank)%3A%0A%20%20%20%20omega_shank_G%20%3D%20np.einsum(%22nji%2Cnj-%3Eni%22%2C%20R_lG%2C%20omega_shank)%20%20%23%20R_lG%5ET%20omega_l%0A%20%20%20%20_speed%20%3D%20np.linalg.norm(omega_shank_G%2C%20axis%3D1)%0A%20%20%20%20_fast%20%3D%20_speed%20%3E%20np.radians(30)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20%22Median%20fraction%20of%20%7Comega%7C%20along%20the%20laboratory's%20Z%20axis%20(when%20%7Comega%7C%20%3E%2030%20deg%2Fs)%3A%22%2C%0A%20%20%20%20%20%20%20%20f%22%7Bnp.median(np.abs(omega_shank_G%5B_fast%2C%202%5D)%20%2F%20_speed%5B_fast%5D)%3A.2f%7D%22%2C%0A%20%20%20%20)%0A%20%20%20%20print(f%22Median%20angle%20between%20the%20shank's%20z%20axis%20and%20the%20laboratory's%20Z%3A%20%7Bnp.median(np.degrees(np.arccos(R_lG%5B%3A%2C%202%2C%202%5D)))%3A.0f%7D%20degrees%22)%0A%0A%20%20%20%20_v_rel%20%3D%20np.gradient(kjc%2C%20dt_walk%2C%20axis%3D0%2C%20edge_order%3D2)%20-%20np.gradient(ajc%2C%20dt_walk%2C%20axis%3D0%2C%20edge_order%3D2)%0A%20%20%20%20_err%20%3D%20np.linalg.norm(_v_rel%20-%20np.cross(omega_shank_G%2C%20kjc%20-%20ajc)%2C%20axis%3D1)%0A%20%20%20%20_r_hat%20%3D%20(kjc%20-%20ajc)%20%2F%20np.linalg.norm(kjc%20-%20ajc%2C%20axis%3D1%2C%20keepdims%3DTrue)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22%5Cn%7Cv_knee%20-%20v_ankle%20-%20omega%20x%20r%7C%3A%20median%20%7Bnp.median(_err)%3A.1f%7D%20cm%2Fs%2C%20largest%20%7B_err.max()%3A.1f%7D%20cm%2Fs%22%0A%20%20%20%20%20%20%20%20f%22%20(%7Cv_knee%20-%20v_ankle%7C%20median%20%7Bnp.median(np.linalg.norm(_v_rel%2C%20axis%3D1))%3A.0f%7D%20cm%2Fs)%22%0A%20%20%20%20)%0A%20%20%20%20print(f%22Largest%20velocity%20along%20the%20line%20between%20the%20joint%20centers%3A%20%7Bnp.abs(np.sum(_v_rel%20*%20_r_hat%2C%20axis%3D1)).max()%3A.1f%7D%20cm%2Fs%22)%0A%20%20%20%20return%20(omega_shank_G%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%20In%20the%20laboratory%2C%20the%20shank's%20angular%20velocity%20points%20almost%20along%20%24%5Cmathbf%7BZ%7D%24%2C%20the%20medio-lateral%20axis%3A%20in%20the%20median%20instant%2C%2097%25%20of%20its%20magnitude.%20The%20shank%20rotates%20in%20the%20sagittal%20plane%2C%20as%20anyone%20watching%20a%20person%20walk%20would%20expect.%20In%20the%20shank's%20own%20basis%20that%20same%20rotation%20looks%20less%20tidy%2C%20because%20the%20shank's%20%24z%24%20axis%20is%20turned%20about%20%2424%5E%5Ccirc%24%20away%20from%20the%20laboratory's%20%24%5Cmathbf%7BZ%7D%24%20(the%20external%20rotation%20discussed%20in%20Rigid-body%20transformations%20in%203D)%3A%20part%20of%20the%20sagittal%20rotation%20shows%20up%20as%20%24%5Comega_x%24%2C%20up%20to%20%24137%5E%5Ccirc%24%2Fs.%20Components%20are%20always%20components%20*in%20some%20basis*%2C%20and%20the%20basis%20must%20be%20stated.%0A%0A%20%20%20%20The%20rigid-body%20prediction%20for%20the%20knee%20works%20well%20in%20the%20median%20instant%2C%20with%20an%20error%20of%202.5%20cm%2Fs%20on%20a%20relative%20velocity%20of%2075%20cm%2Fs%2C%20but%20misses%20by%20up%20to%2020%20cm%2Fs%20at%20worst.%20All%20of%20that%20miss%20is%20along%20the%20line%20between%20the%20joint%20centers%2C%20the%20one%20direction%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20%5Cvec%7B%5Cmathbf%7Br%7D%7D%24%20can%20never%20produce%3A%20the%20distance%20between%20the%20joint%20centers%20is%20changing.%20The%20markers%20move%20on%20the%20skin%2C%20which%20is%20the%20rigidity%20test%20of%20%5BKinematics%20of%20a%20rigid%20body%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_of_rigid_body.py)%20failing%20in%203D.%0A%0A%20%20%20%20**Challenge%202.**%20Smooth%20the%20marker%20trajectories%20with%20a%20low-pass%20filter%20before%20building%20the%20basis%20(see%20%5BData%20filtering%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fdata_filtering.py))%2C%20for%20example%20a%20fourth-order%20Butterworth%20filter%20at%206%20Hz%2C%20and%20compute%20the%20shank's%20angular%20velocity%20again.%20How%20much%20does%20its%20peak%20change%3F%20And%20the%20miss%20along%20the%20line%20between%20the%20joint%20centers%3F%0A%0A%20%20%20%20**Exercise%206.**%20At%20the%20instant%20when%20the%20shank%20turns%20fastest%2C%20how%20far%20is%20its%20axis%20of%20rotation%20from%20the%20laboratory's%20medio-lateral%20axis%20%24%5Cmathbf%7BZ%7D%24%3F%20Give%20the%20angle%20in%20degrees.%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%20omega_shank_G%2C%20t_walk)%3A%0A%20%20%20%20_i%20%3D%20np.argmax(np.linalg.norm(omega_shank_G%2C%20axis%3D1))%0A%20%20%20%20_w%20%3D%20np.degrees(omega_shank_G%5B_i%5D)%0A%20%20%20%20_angle%20%3D%20np.degrees(np.arccos(abs(_w%5B2%5D)%20%2F%20np.linalg.norm(_w)))%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%20rf%22%22%22%0A%20%20%20%20The%20fastest%20instant%20is%20%24t%20%3D%20%7Bt_walk%5B_i%5D%3A.3f%7D%24%20s%2C%20in%20late%20swing%2C%20where%20the%20angular%20velocity%20in%20the%20laboratory's%20basis%20is%20%24%5Cvec%7B%7B%5Cboldsymbol%7B%7B%5Comega%7D%7D%7D%7D_G%20%3D%20%5B%7B_w%5B0%5D%3A.1f%7D%2C%5C%3B%20%7B_w%5B1%5D%3A.1f%7D%2C%5C%3B%20%7B_w%5B2%5D%3A.1f%7D%5D%5E%5Ccirc%24%2Fs%2C%20with%20magnitude%20%24%7Bnp.linalg.norm(_w)%3A.1f%7D%5E%5Ccirc%24%2Fs.%20The%20axis%20of%20rotation%20is%20the%20direction%20of%20%24%5Cvec%7B%7B%5Cboldsymbol%7B%7B%5Comega%7D%7D%7D%7D_G%24%2C%20and%20its%20angle%20with%20%24%5Cmathbf%7B%7BZ%7D%7D%24%20comes%20from%20the%20dot%20product%20with%20%24%5Chat%7B%7B%5Cmathbf%7B%7Bk%7D%7D%7D%7D%24%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cphi%20%3D%20%5Carccos%5Cfrac%7B%7B%7C%5Comega_Z%7C%7D%7D%7B%7B%5CVert%5Cvec%7B%7B%5Cboldsymbol%7B%7B%5Comega%7D%7D%7D%7D_G%5CVert%7D%7D%20%3D%20%5Carccos%5Cfrac%7B%7B%7Babs(_w%5B2%5D)%3A.1f%7D%7D%7D%7B%7B%7Bnp.linalg.norm(_w)%3A.1f%7D%7D%7D%20%3D%20%7B_angle%3A.1f%7D%5E%5Ccirc%0A%20%20%20%20%24%24%0A%0A%20%20%20%20At%20its%20fastest%2C%20the%20shank%20turns%20about%20an%20axis%20within%20%24%7B_angle%3A.0f%7D%5E%5Ccirc%24%20of%20the%20medio-lateral%20direction%2C%20much%20closer%20than%20its%20own%20%24z%24%20axis%2C%20which%20is%20about%20%2424%5E%5Ccirc%24%20away.%0A%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Example%3A%20a%20gyroscope%20on%20the%20shank%0A%0A%20%20%20%20Wearable%20inertial%20sensors%20are%20an%20alternative%20to%20cameras.%20Their%20gyroscopes%20measure%20the%20angular%20velocity%20directly%2C%20as%20the%20three%20components%20in%20the%20sensor's%20own%20basis%2C%20the%20same%20vector%20our%20formula%20produces%20from%20markers.%20What%20they%20cannot%20do%20is%20know%20how%20they%20were%20strapped%20on.%0A%0A%20%20%20%20Suppose%20two%20sensors%20are%20strapped%20to%20the%20same%20right%20shank%2C%20each%20turned%20by%20%2420%5E%5Ccirc%24%20about%20the%20shank's%20long%20axis%20relative%20to%20the%20shank's%20anatomical%20basis%2C%20one%20inwards%20(towards%20the%20other%20leg)%20and%20one%20outwards.%20Both%20are%20attached%20to%20the%20same%20rigid%20body%2C%20so%20both%20experience%20the%20same%20angular%20velocity%3B%20each%20reports%20it%20in%20its%20own%20basis%2C%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7Bsensor%7D%20%3D%20%5Cmathbf%7BR%7D_%7Bs%2Fl%7D%5C%2C%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_l%24%2C%20where%20the%20rows%20of%20%24%5Cmathbf%7BR%7D_%7Bs%2Fl%7D%24%20are%20the%20sensor's%20versors%20written%20in%20the%20shank's%20basis.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%20the%20shank's%20peak%20angular%20velocity%20about%20its%20own%20%24z%24%20axis%20is%20%24307%5E%5Ccirc%24%2Fs.%20Will%20the%20%24z%24%20gyroscopes%20of%20the%20two%20sensors%20read%20more%2C%20less%2C%20or%20the%20same%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20omega_shank)%3A%0A%20%20%20%20def%20_sensor_basis(theta_deg)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Versors%20(rows)%20of%20a%20sensor%20turned%20by%20theta%20about%20the%20shank's%20y%20axis%2C%20in%20the%20shank's%20basis.%22%22%22%0A%20%20%20%20%20%20%20%20_c%2C%20_s%20%3D%20np.cos(np.radians(theta_deg))%2C%20np.sin(np.radians(theta_deg))%0A%20%20%20%20%20%20%20%20return%20np.array(%5B%5B_c%2C%200%2C%20-_s%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B_s%2C%200%2C%20_c%5D%5D)%0A%0A%20%20%20%20print(f%22Shank's%20own%20z%20axis%3A%20%20%20%20%20%20%20%20%20peak%20omega_z%20%3D%20%7Bnp.degrees(omega_shank%5B%3A%2C%202%5D).max()%3A5.1f%7D%20deg%2Fs%22)%0A%20%20%20%20for%20_theta%2C%20_name%20in%20%5B(20%2C%20%22turned%2020%20deg%20inwards%3A%20%22)%2C%20(-20%2C%20%22turned%2020%20deg%20outwards%3A%22)%5D%3A%0A%20%20%20%20%20%20%20%20_omega_sensor%20%3D%20omega_shank%20%40%20_sensor_basis(_theta).T%0A%20%20%20%20%20%20%20%20_deg%20%3D%20np.degrees(_omega_sensor)%0A%20%20%20%20%20%20%20%20print(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22Sensor%20%7B_name%7D%20peak%20omega_z%20%3D%20%7B_deg%5B%3A%2C%202%5D.max()%3A5.1f%7D%20deg%2Fs%2C%20omega_x%20from%20%7B_deg%5B%3A%2C%200%5D.min()%3A6.1f%7D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%20to%20%7B_deg%5B%3A%2C%200%5D.max()%3A5.1f%7D%2C%20peak%20%7Comega%7C%20%3D%20%7Bnp.linalg.norm(_deg%2C%20axis%3D1).max()%3A.1f%7D%20deg%2Fs%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%20Neither%20reads%20%24307%5E%5Ccirc%24%2Fs.%20The%20sensor%20turned%20inwards%20reads%20a%20peak%20of%20%24330.1%5E%5Ccirc%24%2Fs%20on%20its%20%24z%24%20gyroscope%2C%20more%20than%20the%20shank's%20own%20%24z%24%20component%20and%20almost%20the%20whole%20magnitude%2C%20while%20its%20%24x%24%20gyroscope%20stays%20within%20%24-36%24%20and%20%2457%5E%5Ccirc%24%2Fs.%20The%20sensor%20turned%20outwards%20reads%20only%20%24247.4%5E%5Ccirc%24%2Fs%20about%20%24z%24%2C%20and%20up%20to%20%24221%5E%5Ccirc%24%2Fs%20about%20%24x%24.%20Both%20agree%20on%20the%20magnitude%2C%20%24330.3%5E%5Ccirc%24%2Fs%2C%20the%20one%20quantity%20that%20does%20not%20depend%20on%20the%20basis.%0A%0A%20%20%20%20The%20inward%20turn%20happens%20to%20undo%20the%20shank%20basis's%20external%20rotation%20of%20about%20%2424%5E%5Ccirc%24%2C%20so%20it%20lines%20the%20sensor's%20%24z%24%20axis%20up%20with%20the%20actual%20axis%20of%20rotation%20of%20walking%2C%20close%20to%20%24%5Cmathbf%7BZ%7D%24.%20A%20sensor's%20components%20are%20only%20as%20meaningful%20as%20its%20alignment%2C%20which%20is%20why%20inertial%20sensors%20are%20calibrated%20with%20known%20postures%20or%20movements%20before%20their%20readings%20are%20labelled%20%22flexion%22%20or%20%22rotation%22.%0A%0A%20%20%20%20**Guiding%20questions%202.**%0A%0A%20%20%20%201.%20A%20sensor%20strapped%20turned%20by%20%2490%5E%5Ccirc%24%20about%20the%20long%20axis%20would%20read%20the%20sagittal%20rotation%20on%20which%20gyroscope%3F%0A%20%20%20%202.%20Why%20can%20no%20mounting%20change%20the%20reading%20of%20the%20%24y%24%20gyroscope%20in%20this%20example%3F%0A%20%20%20%203.%20If%20you%20know%20the%20magnitude%20of%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20and%20its%20component%20along%20one%20axis%2C%20what%20do%20you%20know%20about%20its%20direction%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%20Checkpoint%20questions%0A%0A%20%20%20%20Pause%20here%20before%20the%20problems.%0A%0A%20%20%20%201.%20Go%20back%20to%20your%20pen%20in%20Challenge%200.%20Is%20there%20a%20single%20axis%20of%20rotation%20at%20each%20instant%3F%20What%20is%20the%20angular%20velocity%20of%20the%20pen%20in%20terms%20of%20the%20spin%20and%20the%20swing%3F%0A%20%20%20%202.%20Why%20can%20angular%20velocities%20about%20different%20axes%20be%20added%20as%20vectors%2C%20while%20angles%20of%20rotation%20about%20different%20axes%20cannot%3F%0A%20%20%20%203.%20The%20dot-product%20formula%20gives%20%24%5Comega_1%24%2C%20%24%5Comega_2%24%2C%20%24%5Comega_3%24.%20In%20which%20basis%20are%20they%20components%2C%20and%20what%20do%20you%20need%20to%20express%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20in%20the%20laboratory's%20basis%3F%0A%20%20%20%204.%20What%20happens%20to%20the%20formula%20if%20the%20basis%20built%20from%20the%20markers%20is%20left-handed%3F%0A%20%20%20%205.%20A%20colleague%20reports%20the%20%22angular%20velocity%20of%20the%20shank%20about%20its%20long%20axis%22%20as%20the%20derivative%20of%20%24%5Cbeta%24.%20Under%20what%20conditions%20would%20that%20be%20correct%3F%0A%20%20%20%206.%20The%20pendulum's%20angular%20velocity%20always%20pointed%20along%20one%20horizontal%20line.%20What%20would%20you%20have%20to%20see%20in%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24%20to%20conclude%20that%20a%20movement%20is%20genuinely%20three-dimensional%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Problems%0A%0A%20%20%20%201.%20Initially%2C%20the%20lateral%20malleolus%2C%20medial%20malleolus%2C%20fibular%20head%20and%20medial%20condyle%20of%20the%20leg%20have%20the%20following%20positions%20(described%20in%20the%20laboratory%20coordinate%20system%20with%20coordinates%20%24x%2C%20y%2C%20z%24%20in%20cm%2C%20the%20%24x%24%20axis%20pointing%20forward%20and%20the%20%24y%24%20axis%20pointing%20upward)%3A%20lateral%20malleolus%20(lm%20%3D%20%5B2.92%2C%2010.10%2C%2018.85%5D)%2C%20medial%20malleolus%20(mm%20%3D%20%5B2.71%2C%2010.22%2C%2026.52%5D)%2C%20fibular%20head%20(fh%20%3D%20%5B5.05%2C%2041.90%2C%2015.41%5D)%2C%20and%20medial%20condyle%20(mc%20%3D%20%5B8.29%2C%2041.88%2C%2026.52%5D).%20After%200.05%20seconds%20the%20markers%20have%20the%20following%20positions%3A%20lateral%20malleolus%20(lm%20%3D%20%5B2.95%2C%2010.19%2C%2018.41%5D)%2C%20medial%20malleolus%20(mm%20%3D%20%5B3.16%2C%2010.04%2C%2026.10%5D)%2C%20fibular%20head%20(fh%20%3D%20%5B4.57%2C%2042.13%2C%2015.97%5D)%2C%20and%20medial%20condyle%20(mc%20%3D%20%5B8.42%2C%2041.76%2C%2026.90%5D).%20Estimate%20the%20average%20angular%20velocity%20of%20the%20leg%20over%20the%20interval.%20State%20the%20basis%20construction%20and%20finite-rotation%20or%20finite-difference%20convention%3B%20two%20frames%20do%20not%20identify%20its%20instantaneous%20time%20course.%0A%0A%20%20%20%202.%20Differentiating%20%24%5Chat%7B%5Cmathbf%7Be%7D%7D_2%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_3%20%3D%200%24%2C%20show%20that%20%24%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_2%7D%7Bdt%7D%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_3%20%3D%20-%5Cfrac%7Bd%5Chat%7B%5Cmathbf%7Be%7D%7D_3%7D%7Bdt%7D%5Ccdot%5Chat%7B%5Cmathbf%7Be%7D%7D_2%24%2C%20and%20write%20a%20second%20formula%20for%20each%20component%20of%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%24.%20Compute%20the%20shank's%20angular%20velocity%20with%20both%20formulas%3A%20do%20they%20agree%20with%20measured%20data%3F%0A%0A%20%20%20%203.%20A%20body%20rotates%20with%20a%20constant%20angular%20velocity%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%3D%20%5B0%2C%200%2C%201%5D%24%20rad%2Fs%20in%20its%20own%20basis.%20Using%20the%20matrix%20%24%5Cmathbf%7BE%7D%24%20of%20the%20%24xyz%24%20sequence%2C%20calculate%20the%20Cardan%20angle%20rates%20when%20%24%5Cbeta%20%3D%200%24%2C%20%2460%5E%5Ccirc%24%20and%20%2489%5E%5Ccirc%24%20(with%20%24%5Cgamma%20%3D%200%24).%20What%20happens%20as%20%24%5Cbeta%24%20approaches%20%2490%5E%5Ccirc%24%3F%0A%0A%20%20%20%204.%20Derive%20the%20matrix%20%24%5Cmathbf%7BE%7D%24%20for%20the%20%24zxy%24%20sequence%2C%20which%20puts%20the%20rotation%20about%20the%20medio-lateral%20axis%20first%2C%20and%20use%20it%20with%20the%20shank's%20angular%20velocity%20to%20obtain%20the%20angle%20rates.%20Compare%20the%20rate%20of%20the%20medio-lateral%20angle%20with%20%24%5Comega_z%24.%20Is%20the%20difference%20smaller%20than%20for%20the%20%24xyz%24%20sequence%3F%0A%0A%20%20%20%205.%20Compute%20the%20angular%20velocity%20of%20the%20left%20shank%20in%20%60walk.trc%60%2C%20with%20the%20markers%20%60L.Ankle%60%2C%20%60L.Ankle.Medial%60%2C%20%60L.HF%60%20and%20%60L.Knee.Medial%60.%20Which%20difference%20between%20the%20malleoli%20must%20you%20use%20for%20the%20%24x%24%20axis%20to%20point%20forward%3F%20Compare%20the%20peak%20angular%20velocity%20of%20the%20two%20shanks%2C%20and%20explain%20the%20difference%20in%20their%20timing.%0A%0A%20%20%20%206.%20Build%20a%20basis%20for%20the%20right%20thigh%20in%20%60walk.trc%60%20from%20the%20greater%20trochanter%20(%60R.GTR%60)%20and%20the%20lateral%20and%20medial%20knee%20markers%20(%60R.Knee%60%2C%20%60R.Knee.Medial%60)%2C%20compute%20its%20angular%20velocity%2C%20and%20obtain%20the%20angular%20velocity%20of%20the%20shank%20relative%20to%20the%20thigh%2C%20%24%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7Bshank%7D%20-%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D_%7Bthigh%7D%24%2C%20expressed%20in%20the%20thigh's%20basis.%20How%20much%20of%20it%20is%20about%20the%20thigh's%20medio-lateral%20axis%3F%20Does%20the%20knee%20behave%20like%20a%20hinge%2C%20and%20what%20in%20the%20marker%20set%20could%20make%20it%20look%20less%20like%20one%20than%20it%20is%3F%20(The%20virtual%20hip%20joint%20center%20in%20the%20file%2C%20%60V_R.Hip_JC%60%2C%20is%20empty.)%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.%20The%20two%20frames%20determine%20an%20interval%20estimate%2C%20not%20a%20unique%20instantaneous%20angular%20velocity.%20With%20the%20right-shank%20basis%20used%20here%20and%20the%20rotation-vector%20logarithm%20over%200.05%20s%2C%20the%20laboratory%20estimate%20is%20%24(0.69218%2C1.09415%2C0.21852)%24%20rad%2Fs.%20In%20the%20initial%20shank%20basis%20it%20is%20%24(-0.56310%2C1.15621%2C-0.26479)%24%20rad%2Fs.%20Different%20finite-difference%20estimators%20agree%20only%20in%20the%20small-step%20limit.%0A%20%20%20%202.%20%24%5Comega_1%3D-%5Cdot%20e_3%5Ccdot%20e_2%24%2C%20%24%5Comega_2%3D-%5Cdot%20e_1%5Ccdot%20e_3%24%2C%20%24%5Comega_3%3D-%5Cdot%20e_2%5Ccdot%20e_1%24.%20Exact%20differentiable%20orthonormal%20bases%20give%20identical%20formulas.%20Numerical%20differences%20of%20noisy%20sampled%20bases%20need%20not%20preserve%20the%20product%20rule%20exactly%2C%20so%20small%20discrepancies%20remain.%0A%20%20%20%203.%20With%20the%20stated%20%24%5Comega%3D(0%2C0%2C1)%24%20and%20%24%5Cgamma%3D0%24%2C%20the%20rates%20are%20%24(%5Cdot%5Calpha%2C%5Cdot%5Cbeta%2C%5Cdot%5Cgamma)%3D(0%2C0%2C1)%24%20rad%2Fs%20at%20all%20three%20specified%20angles.%20They%20do%20**not**%20diverge%20for%20this%20particular%20vector.%20At%20%24%5Cbeta%3D90%5E%5Ccirc%24%2C%20the%20rates%20are%20nonunique%3A%20%24%5Cdot%5Cbeta%3D0%24%20and%20%24%5Cdot%5Calpha%2B%5Cdot%5Cgamma%3D1%24.%20By%20contrast%2C%20the%20input%20%24(1%2C0%2C0)%24%20gives%20%24(%5Csec%5Cbeta%2C0%2C-%5Ctan%5Cbeta)%24%20away%20from%20the%20singularity.%0A%20%20%20%204.%20For%20intrinsic%20%24zxy%24%20angles%20%24(a%2Cb%2Cc)%24%20and%20body%20angular-velocity%20components%20ordered%20%24(x%2Cy%2Cz)%24%2C%20%24E%3D%5B%5B-%5Csin%20c%5Ccos%20b%2C%5Ccos%20c%2C0%5D%2C%5B%5Csin%20b%2C0%2C1%5D%2C%5B%5Ccos%20c%5Ccos%20b%2C%5Csin%20c%2C0%5D%5D%24.%20For%20this%20recording%2C%20RMS%20difference%20between%20the%20first%20%24zxy%24%20angle%20rate%20and%20body%20%24%5Comega_z%24%20is%20about%2016.29%C2%B0%2Fs%2C%20versus%2038.41%C2%B0%2Fs%20for%20the%20%24xyz%24%20medio-lateral%20angle%20rate.%20It%20is%20smaller%20here%2C%20not%20guaranteed%20for%20every%20movement.%0A%20%20%20%205.%20Use%20medial%20minus%20lateral%20for%20the%20left%20shank%E2%80%99s%20temporary%20medio-lateral%20direction.%20Peak%20magnitudes%20are%20about%20330.35%C2%B0%2Fs%20on%20the%20right%20at%200.293%20s%20and%20348.17%C2%B0%2Fs%20on%20the%20left%20at%200.980%20s.%20Their%20timing%20reflects%20alternating%20limbs%20and%20the%20trial%E2%80%99s%20chosen%20start%2C%20with%20natural%20asymmetry%20and%20measurement%20error.%0A%20%20%20%206.%20In%20the%20thigh%20basis%2C%20the%20medio-lateral%20component%20has%20peak%20magnitude%20about%20392.58%C2%B0%2Fs%20and%20RMS%20magnitude%20about%2090.9%25%20of%20the%20RMS%20total%20relative%20angular-speed%20magnitude.%20It%20is%20predominantly%20hinge-like%2C%20with%20other%20components%20present.%20Greater-trochanter%20placement%2C%20skin%20movement%20and%20the%20approximate%20thigh%20long%20axis%20can%20create%20apparent%20non-hinge%20motion.%0A%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%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-%20%5BKinematics%20of%20a%20rigid%20body%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_of_rigid_body.py)%3A%20the%20planar%20angular%20velocity%2C%20%24%5Cvec%7B%5Cmathbf%7Bv%7D%7D%20%3D%20%5Cvec%7B%5Cboldsymbol%7B%5Comega%7D%7D%20%5Ctimes%20%5Cvec%7B%5Cmathbf%7Br%7D%7D%24%20and%20the%20rigidity%20test.%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%20rotation%20matrices%2C%20Cardan%20angles%2C%20gimbal%20lock%20and%20the%20stride%20used%20here.%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%20building%20the%20body's%20basis%20from%20markers%2C%20and%20how%20marker%20errors%20become%20errors%20in%20its%20axes.%0A%20%20%20%20-%20%5BKinetics%20of%20a%203D%20rigid%20body%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinetics_3d_rigid_body.py)%3A%20where%20the%20angular%20velocity%20is%20used%2C%20in%20the%20angular%20momentum%20and%20the%20Newton%E2%80%93Euler%20equations.%0A%20%20%20%20-%20%5BData%20filtering%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fdata_filtering.py)%3A%20what%20to%20do%20before%20differentiating%20measured%20positions.%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%20Video%20lectures%20on%20the%20Internet%0A%0A%20%20%20%20%5BLynch%20and%20Park%3A%20rotation%20matrices%5D(https%3A%2F%2Fmodernrobotics.northwestern.edu%2Fnu-gm-book-resource%2F3-2-1-rotation-matrices-part-1-of-2%2F)%20explains%20orthogonality%2C%20right-handedness%20and%20what%20each%20matrix%20column%20represents.%20Relate%20the%20displayed%20axes%20to%20the%20marker-derived%20basis%20in%20this%20guide.%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-%20Kane%20T%2C%20Levinson%20D%20(1985)%20%5BDynamics%3A%20Theory%20and%20Applications%5D(https%3A%2F%2Fecommons.cornell.edu%2Fhandle%2F1813%2F638).%20McGraw-Hill%2C%20Inc.%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
92cf598070638877ff54cd8718712c9b