%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%22marimo%3E%3D0.23.9%22%2C%20%22numpy%3E%3D2.0%22%2C%20%22matplotlib%3E%3D3.9%22%2C%20%22pandas%3E%3D2.2%22%2C%20%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%20kinematics%20in%20a%20plane%20(2D)%0A%0A%20%20%20%20%3E%20Marcos%20Duarte%2C%20Renato%20Naville%20Watanabe%3Cbr%3E%0A%20%20%20%20%3E%20%5BLaboratory%20of%20Biomechanics%20and%20Motor%20Control%5D(https%3A%2F%2Fbmclab.pesquisa.ufabc.edu.br%2F)%3Cbr%3E%0A%20%20%20%20%3E%20Federal%20University%20of%20ABC%2C%20Brazil%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20How%20to%20use%20this%20guide%0A%0A%20%20%20%20Human%20motion%20is%20a%20combination%20of%20linear%20and%20angular%20movement%2C%20and%20it%20happens%20in%20three-dimensional%20space.%20For%20many%20movements%2C%20depending%20on%20the%20detail%20the%20analysis%20needs%2C%20it%20is%20enough%20to%20study%20the%20motion%20in%20its%20main%20plane%3A%20walking%20seen%20from%20the%20side%2C%20a%20squat%2C%20the%20swing%20of%20an%20arm.%20The%20simplification%20is%20welcome%20because%20a%20planar%20(2D)%20analysis%20is%20far%20cheaper%20than%20a%203D%20one.%20One%20camera%20can%20replace%20several%2C%20and%20trigonometry%20can%20replace%20rotation%20matrices.%0A%0A%20%20%20%20This%20notebook%20is%20about%20angles%20in%20that%20plane.%20It%20covers%20how%20to%20compute%20them%20from%20marker%20coordinates%20without%20falling%20into%20the%20classic%20traps%2C%20how%20to%20turn%20two%20segment%20angles%20into%20a%20joint%20angle%2C%20and%20how%20to%20differentiate%20an%20angle%20into%20an%20angular%20velocity%20and%20an%20angular%20acceleration.%20It%20ends%20with%20real%20data%2C%20the%20leg%20of%20a%20woman%20walking%2C%20and%20with%20the%20link%20between%20angular%20and%20linear%20kinematics.%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%3B%20the%20prediction%20is%20the%20point%2C%20and%20being%20wrong%20is%20the%20most%20useful%20thing%20that%20can%20happen%20to%20you%20here.%0A%0A%20%20%20%20You%20will%20need%20the%20dot%20and%20cross%20products%20from%20%5BScalar%20and%20vector%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fscalar_vector.py)%20and%20the%20finite%20differences%20from%20%5BKinematics%20of%20a%20particle%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_particle.py).%0A%0A%20%20%20%20**Challenge%200.**%20Stand%20up%20and%20straighten%20one%20knee.%20Write%20down%20the%20knee%20angle.%20Now%20write%20down%20a%20second%20number%2C%20just%20as%20defensible%2C%20for%20exactly%20the%20same%20posture.%20Keep%20both%3B%20the%20next%20section%20is%20about%20why%20you%20needed%20two.%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%20What%20is%20a%20knee%20angle%3F%0A%0A%20%20%20%20Two%20gait%20laboratories%20measure%20the%20same%20person%20standing%20upright.%20One%20reports%20a%20knee%20angle%20of%20%240%5Eo%24%2C%20the%20other%20%24180%5Eo%24.%20Both%20are%20right.%0A%0A%20%20%20%20An%20angle%20is%20always%20measured%20*between%20two%20specific%20things*%2C%20*from*%20one%20of%20them%20*to*%20the%20other%2C%20in%20a%20chosen%20direction.%20Change%20any%20of%20those%20choices%20and%20the%20number%20changes%2C%20while%20the%20knee%20stays%20exactly%20where%20it%20was.%20The%20figure%20below%20shows%20the%20convention%20used%20in%20Winter's%20textbook%2C%20which%20is%20also%20the%20one%20used%20for%20the%20data%20at%20the%20end%20of%20this%20notebook%3A%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%2Fjointangles.png%3Fraw%3D1%22%20width%3D350%20alt%3D%22Joint%20angle%20convention%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.%20Convention%20for%20the%20sagittal%20joint%20angles%20of%20the%20lower%20limb%20(from%20Winter%2C%202009).%3C%2Fspan%3E%0A%0A%20%20%20%20In%20this%20convention%2C%20each%20*segment*%20angle%20is%20measured%20counterclockwise%20from%20the%20forward%20horizontal%2C%20with%20the%20segment%20pointing%20from%20its%20distal%20marker%20to%20its%20proximal%20one%3B%20for%20instance%2C%20the%20leg%20(shank)%20angle%20%24%5Ctheta_%7B43%7D%24%20goes%20from%20the%20ankle%2C%20marker%204%2C%20to%20the%20head%20of%20the%20fibula%2C%20marker%203.%20A%20*joint*%20angle%20is%20then%20a%20difference%20of%20segment%20angles.%20The%20knee%20angle%20is%20%24%5Ctheta_%7B21%7D-%5Ctheta_%7B43%7D%24%2C%20positive%20for%20flexion%2C%20so%20a%20straight%20knee%20is%20at%20%240%5Eo%24.%20Many%20clinicians%20report%20instead%20the%20included%20angle%20between%20thigh%20and%20leg%2C%20which%20is%20%24180%5Eo%24%20for%20the%20same%20straight%20knee.%0A%0A%20%20%20%20**Guiding%20questions%200.**%0A%0A%20%20%20%201.%20In%20the%20convention%20of%20the%20figure%2C%20roughly%20what%20is%20the%20knee%20angle%20in%20a%20deep%20squat%3F%20And%20the%20included%20angle%3F%0A%20%20%20%202.%20Why%20does%20the%20ankle%20formula%20in%20the%20figure%20add%20%2490%5Eo%24%3F%0A%20%20%20%203.%20A%20report%20says%20%22peak%20knee%20flexion%20of%20%2460%5Eo%24%22%20and%20nothing%20more.%20What%20do%20you%20need%20to%20ask%20before%20comparing%20that%20number%20with%20your%20own%20data%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%20computation%2C%20pandas%20reads%20the%20data%20file%20at%20the%20end%2C%20and%20Matplotlib%20draws%20the%20plots.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20from%20notebook_resources%20import%20repo_file%0A%20%20%20%20except%20ModuleNotFoundError%20as%20_error%3A%0A%20%20%20%20%20%20%20%20if%20_error.name%20!%3D%20%22notebook_resources%22%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%0A%20%20%20%20%20%20%20%20raise%20ModuleNotFoundError(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22This%20notebook%20needs%20notebook_resources.py.%20Download%20it%20from%3A%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fraw.githubusercontent.com%2FBMClab%2FBMC%2Fmaster%2Ffunctions%2Fnotebook_resources.py%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Save%20it%20in%20the%20same%20folder%20as%20this%20notebook%2C%20then%20rerun%20this%20cell.%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22notebook_resources%22%2C%0A%20%20%20%20%20%20%20%20)%20from%20None%0A%20%20%20%20return%20(repo_file%2C)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20matplotlib%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20from%20matplotlib.patches%20import%20FancyArrowPatch%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%20FancyArrowPatch%2C%20np%2C%20pd%2C%20plt%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Angles%20in%20a%20plane%0A%0A%20%20%20%20In%20the%20planar%20case%2C%20computing%20an%20angle%20reduces%20to%20trigonometry%20on%20the%20kinematic%20data.%20Given%20the%20coordinates%20in%20the%20plane%20of%20two%20markers%20on%20a%20segment%2C%20as%20in%20the%20figure%20below%2C%20the%20angle%20of%20the%20segment%20can%20be%20found%20with%20the%20inverse%20of%20the%20sine%2C%20the%20cosine%20or%20the%20tangent.%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%2Fsegment.png%3Fraw%3D1%22%20width%3D250%20alt%3D%22segment%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-2%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20A%20segment%20in%20a%20plane%20and%20its%20coordinates.%3C%2Fspan%3E%0A%0A%20%20%20%20The%20inverse%20of%20the%20tangent%20is%20preferred%2C%20because%20it%20uses%20both%20coordinates%20and%20so%20keeps%20its%20accuracy%20at%20every%20orientation.%20For%20the%20segment%20in%20the%20figure%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Ctheta%20%3D%20%5Carctan%5Cleft(%5Cfrac%7By_2-y_1%7D%7Bx_2-x_1%7D%5Cright)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20In%20NumPy%20this%20is%20%60numpy.arctan((y2%20-%20y1)%20%2F%20(x2%20-%20x1))%60.%20But%20the%20division%20throws%20information%20away.%20A%20segment%20at%20%2445%5Eo%24%20and%20the%20same%20segment%20pointing%20the%20opposite%20way%2C%20at%20%24225%5Eo%24%2C%20have%20the%20same%20ratio%20%24%5CDelta%20y%2F%5CDelta%20x%24%2C%20so%20%60arctan%60%20cannot%20tell%20them%20apart.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20what%20%60arctan%60%20returns%20for%20a%20segment%20at%20%24225%5Eo%24.%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%20print(%22Segment%20at%2045%20degrees%2C%20from%20(0%2C%200)%20to%20(1%2C%201)%3A%22)%0A%20%20%20%20print(f%22%20%20arctan%3A%20%20%7Bnp.rad2deg(np.arctan((1%20-%200)%20%2F%20(1%20-%200)))%3A7.1f%7D%22)%0A%20%20%20%20print(f%22%20%20arctan2%3A%20%7Bnp.rad2deg(np.arctan2(1%20-%200%2C%201%20-%200))%3A7.1f%7D%22)%0A%20%20%20%20print(%22Segment%20at%20225%20degrees%2C%20from%20(0%2C%200)%20to%20(-1%2C%20-1)%3A%22)%0A%20%20%20%20print(f%22%20%20arctan%3A%20%20%7Bnp.rad2deg(np.arctan((-1%20-%200)%20%2F%20(-1%20-%200)))%3A7.1f%7D%22)%0A%20%20%20%20print(f%22%20%20arctan2%3A%20%7Bnp.rad2deg(np.arctan2(-1%20-%200%2C%20-1%20-%200))%3A7.1f%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%20%60arctan%60%20says%20%2445%5Eo%24%20for%20both.%20The%20function%20%60numpy.arctan2(y%2C%20x)%60%20receives%20the%20two%20differences%20separately%2C%20so%20it%20knows%20their%20signs%20and%20therefore%20the%20quadrant%2C%20and%20it%20gets%20the%20second%20segment%20right%3A%20%24-135%5Eo%24%20is%20the%20same%20direction%20as%20%24225%5Eo%24.%20Be%20aware%20of%20that%20convention.%20%60arctan2%60%20returns%20angles%20in%20the%20interval%20%24%5B-%5Cpi%2C%20%5Cpi%5D%24%2C%20that%20is%2C%20between%20%24-180%5Eo%24%20and%20%24180%5Eo%24.%0A%0A%20%20%20%20NumPy%20also%20has%20functions%20to%20convert%20an%20angle%20from%20radians%20to%20degrees%20and%20back%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20print(%22np.rad2deg(np.pi)%20%3D%22%2C%20np.rad2deg(np.pi))%0A%20%20%20%20print(%22np.deg2rad(180)%20%3D%22%2C%20np.deg2rad(180))%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%20Two%20turns%20of%20the%20arm%0A%0A%20%20%20%20Let's%20simulate%20the%20planar%20motion%20of%20an%20arm%20performing%20two%20complete%20turns%20around%20the%20shoulder%2C%20at%20one%20turn%20per%20second%2C%20sampled%20at%20100%20Hz%2C%20and%20compute%20its%20angle%20with%20%60arctan2%60.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20sketch%20what%20you%20expect%20the%20angle%20to%20look%20like%20over%20the%20two%20seconds.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt)%3A%0A%20%20%20%20t%20%3D%20np.arange(0%2C%202%2C%200.01)%0A%20%20%20%20x%20%3D%20np.cos(2%20*%20np.pi%20*%20t)%0A%20%20%20%20y%20%3D%20np.sin(2%20*%20np.pi%20*%20t)%0A%20%20%20%20_angle%20%3D%20np.rad2deg(np.arctan2(y%2C%20x))%0A%0A%20%20%20%20plt.figure(figsize%3D(12%2C%204))%0A%20%20%20%20_ax1%20%3D%20plt.subplot2grid((2%2C%203)%2C%20(0%2C%200)%2C%20rowspan%3D2)%0A%20%20%20%20_ax1.plot(x%2C%20y%2C%20%22go%22%2C%20markersize%3D4)%0A%20%20%20%20_ax1.plot(0%2C%200%2C%20%22ko%22%2C%20markersize%3D8)%0A%20%20%20%20_ax1.set_xlabel(%22x%20%5Bm%5D%22)%0A%20%20%20%20_ax1.set_ylabel(%22y%20%5Bm%5D%22)%0A%20%20%20%20_ax1.set_xlim(%5B-1.1%2C%201.1%5D)%0A%20%20%20%20_ax1.set_ylim(%5B-1.1%2C%201.1%5D)%0A%20%20%20%20_ax1.set_aspect(%22equal%22)%0A%20%20%20%20_ax2%20%3D%20plt.subplot2grid((2%2C%203)%2C%20(0%2C%201)%2C%20colspan%3D2)%0A%20%20%20%20_ax2.plot(t%2C%20x%2C%20%22bo%22%2C%20markersize%3D4%2C%20label%3D%22x%22)%0A%20%20%20%20_ax2.plot(t%2C%20y%2C%20%22ro%22%2C%20markersize%3D4%2C%20label%3D%22y%22)%0A%20%20%20%20_ax2.legend(numpoints%3D1%2C%20frameon%3DTrue%2C%20framealpha%3D0.8%2C%20loc%3D%22upper%20right%22)%0A%20%20%20%20_ax2.set_ylabel(%22Position%20%5Bm%5D%22)%0A%20%20%20%20_ax2.set_ylim(%5B-1.1%2C%201.1%5D)%0A%20%20%20%20_ax3%20%3D%20plt.subplot2grid((2%2C%203)%2C%20(1%2C%201)%2C%20colspan%3D2)%0A%20%20%20%20_ax3.plot(t%2C%20_angle%2C%20%22go%22%2C%20markersize%3D4)%0A%20%20%20%20_ax3.set_yticks(np.arange(-180%2C%20181%2C%2090))%0A%20%20%20%20_ax3.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20_ax3.set_ylabel(%22Angle%20%5B%24%5Eo%24%5D%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20t%2C%20x%2C%20y%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%20Because%20the%20output%20of%20%60arctan2%60%20is%20bounded%20to%20%24%5B-180%5Eo%2C%20180%5Eo%5D%24%2C%20the%20angle%20looks%20chopped%3A%20every%20time%20the%20arm%20passes%20%24180%5Eo%24%20it%20appears%20to%20jump%20back%20by%20a%20full%20turn%2C%20which%20it%20obviously%20did%20not%20do.%20Differentiate%20that%20curve%20and%20the%20jump%20becomes%20a%20huge%2C%20completely%20fictitious%20angular%20velocity.%0A%0A%20%20%20%20The%20function%20%60numpy.unwrap%60%20solves%20the%20problem.%20It%20looks%20for%20jumps%20larger%20than%20%24180%5Eo%24%20(%24%5Cpi%24%20rad)%20between%20consecutive%20samples%20and%20removes%20them%20by%20adding%20or%20subtracting%20whole%20turns%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt%2C%20t%2C%20x%2C%20y)%3A%0A%20%20%20%20_angle%20%3D%20np.rad2deg(np.unwrap(np.arctan2(y%2C%20x)))%0A%0A%20%20%20%20_%2C%20_ax%20%3D%20plt.subplots(figsize%3D(8%2C%203))%0A%20%20%20%20_ax.plot(t%2C%20_angle%2C%20%22go%22%2C%20markersize%3D4)%0A%20%20%20%20_ax.set_yticks(np.arange(0%2C%20721%2C%2090))%0A%20%20%20%20_ax.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Angle%20%5B%24%5Eo%24%5D%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Two%20turns%2C%20%24720%5Eo%24%2C%20as%20a%20smooth%20ramp.%20Note%20that%20%60unwrap%60%20expects%20and%20returns%20radians%3B%20convert%20to%20degrees%20afterwards%2C%20as%20above.%0A%0A%20%20%20%20%60unwrap%60%20rests%20on%20an%20assumption%20that%20is%20worth%20knowing%3A%20that%20the%20true%20change%20between%20two%20consecutive%20samples%20is%20less%20than%20half%20a%20turn.%20At%20100%20Hz%20this%20arm%20turns%20%243.6%5Eo%24%20per%20sample%2C%20so%20the%20assumption%20is%20safe.%20It%20is%20not%20safe%20for%20any%20sampling%20rate.%0A%0A%20%20%20%20**Challenge%201.**%20Sample%20the%20same%20two%20turns%20every%200.4%20s%20and%20then%20every%200.6%20s%20(%60np.arange(0%2C%202%2C%200.4)%60)%2C%20and%20unwrap%20each.%20How%20many%20degrees%20does%20%60unwrap%60%20report%20in%20each%20case%2C%20and%20in%20which%20direction%20does%20the%20arm%20seem%20to%20turn%20in%20the%20second%20one%3F%20Where%20have%20you%20seen%20the%20same%20illusion%20in%20a%20film%20of%20a%20spinning%20wheel%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**Exercise%201.**%20A%20segment%20points%20from%20%24(0%2C0)%24%20to%20%24(-1%2C1)%24.%20Compare%20%60atan(y%2Fx)%60%20and%20%60atan2(y%2Cx)%60.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Worked%20solution%20%E2%80%94%20Exercise%201%0A%0A%20%20%20%20The%20ratio%20is%20%24-1%24%2C%20so%20arctangent%20alone%20reports%20%24-45%5E%5Ccirc%24.%20%60atan2(1%2C-1)%60%20keeps%20both%20signs%20and%20returns%20%24135%5E%5Ccirc%24%2C%20the%20correct%20quadrant.%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%20Joint%20angles%0A%0A%20%20%20%20To%20measure%20the%20angle%20of%20a%20joint%2C%20that%20is%2C%20the%20angle%20of%20one%20segment%20relative%20to%20another%2C%20we%20can%20simply%20subtract%20the%20two%20segment%20angles.%20This%20is%20correct%20only%20if%20both%20angles%20are%20in%20the%20same%20plane.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(FancyArrowPatch%2C%20np%2C%20plt)%3A%0A%20%20%20%20x1%2C%20y1%2C%20x2%2C%20y2%20%3D%200.0%2C%200.0%2C%201.0%2C%201.0%20%20%23%20segment%201%0A%20%20%20%20x3%2C%20y3%2C%20x4%2C%20y4%20%3D%201.1%2C%201.0%2C%202.1%2C%200.0%20%20%23%20segment%202%0A%20%20%20%20_arc%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22arrowstyle%22%3A%20%22-%3E%2Chead_length%3D10%2Chead_width%3D5%22%2C%0A%20%20%20%20%20%20%20%20%22connectionstyle%22%3A%20%22arc3%2Crad%3D0.3%22%2C%0A%20%20%20%20%7D%0A%0A%20%20%20%20_%2C%20_ax%20%3D%20plt.subplots(figsize%3D(8%2C%203))%0A%20%20%20%20_ax.plot((x1%2C%20x2)%2C%20(y1%2C%20y2)%2C%20%22b-%22%2C%20(x3%2C%20x4)%2C%20(y3%2C%20y4)%2C%20%22b-%22%2C%20linewidth%3D3)%0A%20%20%20%20_ax.plot((x1%2C%20x2%2C%20x3%2C%20x4)%2C%20(y1%2C%20y2%2C%20y3%2C%20y4)%2C%20%22ro%22%2C%20markersize%3D12)%0A%20%20%20%20_ax.add_patch(%0A%20%20%20%20%20%20%20%20FancyArrowPatch(posA%3D(x1%20%2B%20np.sqrt(2)%20%2F%203%2C%20y1)%2C%20posB%3D(x2%20%2F%203%2C%20y2%20%2F%203)%2C%20**_arc)%0A%20%20%20%20)%0A%20%20%20%20_ax.text(1%20%2F%202%2C%201%20%2F%205%2C%20r%22%24%5Ctheta_1%24%22%2C%20fontsize%3D24)%0A%20%20%20%20_ax.add_patch(%0A%20%20%20%20%20%20%20%20FancyArrowPatch(%0A%20%20%20%20%20%20%20%20%20%20%20%20posA%3D(x4%20%2B%20np.sqrt(2)%20%2F%203%2C%20y4)%2C%20posB%3D(x4%20-%201%20%2F%203%2C%20y4%20%2B%201%20%2F%203)%2C%20**_arc%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_ax.text(x4%20%2B%200.2%2C%20y4%20%2B%200.3%2C%20r%22%24%5Ctheta_2%24%22%2C%20fontsize%3D24)%0A%20%20%20%20_ax.add_patch(%0A%20%20%20%20%20%20%20%20FancyArrowPatch(%0A%20%20%20%20%20%20%20%20%20%20%20%20posA%3D(x2%20-%201%20%2F%203%2C%20y2%20-%201%20%2F%203)%2C%20posB%3D(x3%20%2B%201%20%2F%203%2C%20y3%20-%201%20%2F%203)%2C%20**_arc%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20_ax.text(x1%20%2B%200.8%2C%20y1%20%2B%200.35%2C%20r%22%24%5Ctheta_J%3D%5Ctheta_2-%5Ctheta_1%24%22%2C%20fontsize%3D24)%0A%20%20%20%20_ax.set_xticks((x1%2C%20x2%2C%20x3%2C%20x4))%0A%20%20%20%20_ax.set_xticklabels((%22x1%22%2C%20%22x2%22%2C%20%22x3%22%2C%20%22x4%22)%2C%20fontsize%3D13)%0A%20%20%20%20_ax.set_yticks((y1%2C%20y2))%0A%20%20%20%20_ax.set_xlim(min(x1%2C%20x2%2C%20x3%2C%20x4)%20-%200.1%2C%20max(x1%2C%20x2%2C%20x3%2C%20x4)%20%2B%200.5)%0A%20%20%20%20_ax.set_ylim(min(y1%2C%20y2%2C%20y3%2C%20y4)%20-%200.1%2C%20max(y1%2C%20y2%2C%20y3%2C%20y4)%20%2B%200.1)%0A%20%20%20%20_ax.grid(True%2C%20linestyle%3D%22%3A%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20x1%2C%20x2%2C%20x3%2C%20x4%2C%20y1%2C%20y2%2C%20y3%2C%20y4%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%20joint%20angle%20is%20the%20difference%20between%20the%20adjacent%20segment%20angles%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20x1%2C%20x2%2C%20x3%2C%20x4%2C%20y1%2C%20y2%2C%20y3%2C%20y4)%3A%0A%20%20%20%20ang1%20%3D%20np.rad2deg(np.arctan2(y2%20-%20y1%2C%20x2%20-%20x1))%0A%20%20%20%20ang2%20%3D%20np.rad2deg(np.arctan2(y3%20-%20y4%2C%20x3%20-%20x4))%0A%0A%20%20%20%20print(f%22theta_1%20%3D%20%7Bang1%3A.1f%7D%20degrees%22)%0A%20%20%20%20print(f%22theta_2%20%3D%20%7Bang2%3A.1f%7D%20degrees%22)%0A%20%20%20%20print(f%22theta_J%20%3D%20%7Bang2%20-%20ang1%3A.1f%7D%20degrees%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%20Look%20at%20the%20order%20of%20the%20markers%20in%20the%20two%20calls.%20Segment%201%20points%20from%20marker%201%20to%20marker%202%2C%20and%20segment%202%20from%20marker%204%20to%20marker%203%3A%20in%20both%20cases%20from%20the%20lower%20end%20to%20the%20upper%20end%2C%20as%20Winter's%20convention%20points%20every%20segment%20from%20distal%20to%20proximal.%20Point%20either%20segment%20the%20other%20way%20and%20its%20angle%20changes%20by%20%24180%5Eo%24%2C%20and%20so%20does%20the%20joint%20angle.%20That%20choice%2C%20and%20which%20angle%20is%20subtracted%20from%20which%2C%20*is*%20the%20convention%20from%20the%20section%20on%20knee%20angles.%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%20Angle%20between%20two%20vectors%0A%0A%20%20%20%20Sometimes%20we%20have%20the%203D%20coordinates%20of%20the%20markers%20but%20only%20care%20about%20the%20angle%20between%20two%20segments%20in%20the%20plane%20the%20two%20segments%20define.%20(If%20the%20segments%20also%20move%20considerably%20out%20of%20that%20plane%2C%20this%20simple%20angle%20can%20give%20unexpected%20results.)%20Say%20%60p1%60%20and%20%60p2%60%20are%20the%20coordinates%20of%20the%20markers%20on%20segment%201%2C%20and%20%60p3%60%20and%20%60p4%60%20those%20on%20segment%202%3B%20the%20segments%20are%20then%20the%20vectors%20%24%5Cvec%7B%5Cmathbf%7Ba%7D%7D%20%3D%20p_1%20-%20p_2%24%20and%20%24%5Cvec%7B%5Cmathbf%7Bb%7D%7D%20%3D%20p_4%20-%20p_3%24.%0A%0A%20%20%20%20The%20angle%20between%20them%20follows%20from%20the%20definition%20of%20the%20dot%20product%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cvec%7B%5Cmathbf%7Ba%7D%7D%20%5Ccdot%20%5Cvec%7B%5Cmathbf%7Bb%7D%7D%20%3D%20%5CVert%5Cvec%7B%5Cmathbf%7Ba%7D%7D%5CVert%5C%2C%5CVert%5Cvec%7B%5Cmathbf%7Bb%7D%7D%5CVert%5Ccos(%5Ctheta)%0A%20%20%20%20%5Cquad%20%5CLongrightarrow%20%5Cquad%0A%20%20%20%20%5Ctheta%20%3D%20%5Carccos%5Cleft(%5Cfrac%7B%5Cvec%7B%5Cmathbf%7Ba%7D%7D%20%5Ccdot%20%5Cvec%7B%5Cmathbf%7Bb%7D%7D%7D%7B%5CVert%5Cvec%7B%5Cmathbf%7Ba%7D%7D%5CVert%5C%2C%5CVert%5Cvec%7B%5Cmathbf%7Bb%7D%7D%5CVert%7D%5Cright)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20or%20from%20the%20magnitude%20of%20the%20cross%20product%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5CVert%5Cvec%7B%5Cmathbf%7Ba%7D%7D%20%5Ctimes%20%5Cvec%7B%5Cmathbf%7Bb%7D%7D%5CVert%20%3D%20%5CVert%5Cvec%7B%5Cmathbf%7Ba%7D%7D%5CVert%5C%2C%5CVert%5Cvec%7B%5Cmathbf%7Bb%7D%7D%5CVert%5Csin(%5Ctheta)%0A%20%20%20%20%5Cquad%20%5CLongrightarrow%20%5Cquad%0A%20%20%20%20%5Ctheta%20%3D%20%5Carcsin%5Cleft(%5Cfrac%7B%5CVert%5Cvec%7B%5Cmathbf%7Ba%7D%7D%20%5Ctimes%20%5Cvec%7B%5Cmathbf%7Bb%7D%7D%5CVert%7D%7B%5CVert%5Cvec%7B%5Cmathbf%7Ba%7D%7D%5CVert%5C%2C%5CVert%5Cvec%7B%5Cmathbf%7Bb%7D%7D%5CVert%7D%5Cright)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Each%20has%20a%20weakness.%20The%20arccosine%20loses%20accuracy%20for%20nearly%20parallel%20vectors%2C%20where%20the%20cosine%20barely%20changes%20with%20the%20angle.%20The%20arcsine%20loses%20it%20near%20%2490%5Eo%24%2C%20and%20it%20cannot%20tell%20%24%5Ctheta%24%20from%20%24180%5Eo-%5Ctheta%24%20at%20all.%20Dividing%20the%20second%20equation%20by%20the%20first%20gives%20%24%5Ctan(%5Ctheta)%24%2C%20and%20%60arctan2%60%20combines%20the%20strengths%20of%20both%20with%20no%20division%20by%20the%20norms%3A%0A%0A%20%20%20%20%60%60%60python%0A%20%20%20%20angle%20%3D%20np.arctan2(np.linalg.norm(np.cross(a%2C%20b))%2C%20np.dot(a%2C%20b))%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20See%20%5BScalar%20and%20vector%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fscalar_vector.py)%20for%20a%20review%20of%20the%20dot%20and%20cross%20products.%20Let's%20write%20it%20as%20a%20function%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20angle_between(a%2C%20b)%3A%0A%20%20%20%20%22%22%22Angle%20%5Bdeg%5D%20between%20the%20vectors%20%60a%60%20and%20%60b%60%2C%20in%20the%20interval%20%5B0%2C%20180%5D.%0A%0A%20%20%20%20Works%20for%202D%20and%203D%20vectors%3B%202D%20vectors%20get%20a%20zero%20third%20component%2C%0A%20%20%20%20because%20NumPy's%20cross%20product%20only%20accepts%203D%20vectors.%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20a%20%3D%20np.pad(np.asarray(a%2C%20dtype%3Dfloat)%2C%20(0%2C%203%20-%20len(a)))%0A%20%20%20%20b%20%3D%20np.pad(np.asarray(b%2C%20dtype%3Dfloat)%2C%20(0%2C%203%20-%20len(b)))%0A%0A%20%20%20%20return%20float(np.rad2deg(np.arctan2(np.linalg.norm(np.cross(a%2C%20b))%2C%20np.dot(a%2C%20b))))%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Note%20the%20padding.%20Older%20versions%20of%20NumPy%20quietly%20accepted%202D%20vectors%20in%20%60np.cross%60%20and%20assumed%20a%20zero%20third%20component%3B%20since%20NumPy%202.0%20that%20is%20deprecated%2C%20and%20current%20versions%20raise%20an%20error.%20Our%20function%20adds%20the%20zero%20explicitly.%0A%0A%20%20%20%20We%20can%20use%20it%20to%20calculate%20the%20joint%20angle%20of%20the%20two%20segments%20above%2C%20which%20are%202D%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20p1%2C%20p2%20%3D%20np.array(%5B0%2C%200%5D)%2C%20np.array(%5B1%2C%201%5D)%20%20%23%20segment%201%0A%20%20%20%20p3%2C%20p4%20%3D%20np.array(%5B1.1%2C%201%5D)%2C%20np.array(%5B2.1%2C%200%5D)%20%20%23%20segment%202%0A%0A%20%20%20%20print(f%22Joint%20angle%3A%20%7Bangle_between(p1%20-%20p2%2C%20p4%20-%20p3)%3A.1f%7D%20degrees%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%20same%20%2490%5Eo%24%20as%20the%20difference%20of%20the%20segment%20angles.%0A%0A%20%20%20%20%23%23%23%20The%20missing%20sign%0A%0A%20%20%20%20There%20is%20a%20price%20for%20that%20generality.%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20what%20the%20function%20returns%20for%20a%20joint%20bent%20%2430%5Eo%24%20one%20way%20and%20for%20the%20same%20joint%20bent%20%2430%5Eo%24%20the%20other%20way%2C%20as%20a%20knee%20in%20flexion%20and%20a%20knee%20in%20hyperextension.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20planar_angle(a%2C%20b)%3A%0A%20%20%20%20%22%22%22Signed%20angle%20%5Bdeg%5D%20from%20the%20planar%20vector%20%60a%60%20to%20the%20planar%20vector%20%60b%60.%0A%0A%20%20%20%20Positive%20when%20%60b%60%20is%20counterclockwise%20from%20%60a%60%2C%20in%20the%20interval%20(-180%2C%20180%5D.%0A%20%20%20%20%22%22%22%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20return%20float(np.rad2deg(np.arctan2(a%5B0%5D%20*%20b%5B1%5D%20-%20a%5B1%5D%20*%20b%5B0%5D%2C%20a%5B0%5D%20*%20b%5B0%5D%20%2B%20a%5B1%5D%20*%20b%5B1%5D)))%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_a%20%3D%20%5B1.0%2C%200.0%5D%0A%20%20%20%20for%20_bend%20in%20%5B30%2C%20-30%5D%3A%0A%20%20%20%20%20%20%20%20_b%20%3D%20%5Bnp.cos(np.deg2rad(_bend))%2C%20np.sin(np.deg2rad(_bend))%5D%0A%20%20%20%20%20%20%20%20print(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22bent%20%7B_bend%3A%2Bd%7D%20degrees%3A%20%20angle_between%20-%3E%20%7Bangle_between(_a%2C%20_b)%3A5.1f%7D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%20%20%20planar_angle%20-%3E%20%7Bplanar_angle(_a%2C%20_b)%3A6.1f%7D%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%20%60angle_between%60%20returns%20%2430%5Eo%24%20both%20times.%20It%20uses%20the%20*magnitude*%20of%20the%20cross%20product%2C%20and%20a%20magnitude%20has%20no%20sign.%20That%20is%20not%20a%20flaw%20in%20the%20code%3A%20in%203D%20there%20is%20no%20preferred%20side%20from%20which%20to%20look%20at%20the%20plane%20of%20two%20vectors%2C%20so%20%22clockwise%22%20means%20nothing%20until%20you%20choose%20one.%0A%0A%20%20%20%20In%20a%20plane%20there%20is%20a%20preferred%20side%2C%20the%20one%20we%20look%20from%2C%20along%20%24%2B%5Chat%7B%5Cmathbf%7Bk%7D%7D%24.%20The%20%24z%24%20component%20of%20the%20cross%20product%2C%20%24a_x%20b_y%20-%20a_y%20b_x%24%2C%20keeps%20its%20sign%2C%20and%20%60planar_angle%60%20uses%20it%20to%20tell%20the%20two%20cases%20apart.%20For%20a%20knee%2C%20that%20sign%20is%20the%20difference%20between%20%245%5Eo%24%20of%20flexion%20and%20%245%5Eo%24%20of%20hyperextension%2C%20a%20distinction%20a%20clinician%20will%20care%20about%20a%20great%20deal.%0A%0A%20%20%20%20**Guiding%20questions%201.**%0A%0A%20%20%20%201.%20What%20fixed%20direction%20did%20%60planar_angle%60%20use%20implicitly%20to%20decide%20the%20sign%3F%20What%20happens%20to%20the%20sign%20if%20you%20look%20at%20the%20same%20movement%20from%20the%20other%20side%20of%20the%20plane%2C%20as%20a%20camera%20on%20the%20left%20side%20of%20a%20walkway%20would%2C%20compared%20with%20one%20on%20the%20right%3F%0A%20%20%20%202.%20Compute%20the%20angle%20between%20%24(1%2C%200%2C%200)%24%20and%20%24(%5Ccos%2010%5E%7B-8%7D%2C%20%5Csin%2010%5E%7B-8%7D%2C%200)%24%20with%20%60np.arccos%60%20of%20the%20normalized%20dot%20product%20and%20with%20%60angle_between%60.%20Which%20one%20is%20right%3F%0A%20%20%20%203.%20For%203D%20markers%20of%20a%20knee%2C%20how%20would%20you%20recover%20the%20sign%20of%20the%20angle%3F%20What%20extra%20information%20do%20you%20need%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**Exercise%202.**%20The%20thigh%20and%20shank%20orientations%20are%20%24-70%5E%5Ccirc%24%20and%20%24-110%5E%5Ccirc%24.%20Find%20their%20signed%20relative%20angle%20and%20its%20magnitude.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Worked%20solution%20%E2%80%94%20Exercise%202%0A%0A%20%20%20%20Using%20shank%20minus%20thigh%20gives%20%24-40%5E%5Ccirc%24%3B%20its%20magnitude%20is%20%2440%5E%5Ccirc%24.%20A%20clinical%20flexion%20sign%20needs%20a%20declared%20side%20and%20convention%2C%20not%20an%20unsigned%20dot-product%20angle%20alone.%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%20Angular%20position%2C%20velocity%2C%20and%20acceleration%0A%0A%20%20%20%20In%20a%20plane%2C%20the%20angular%20position%20of%20a%20segment%20is%20described%20by%20one%20angle%2C%20%24%5Ctheta%24%2C%20measured%20about%20the%20axis%20perpendicular%20to%20the%20plane%3B%20the%20motion%2C%20if%20there%20is%20any%2C%20is%20said%20to%20occur%20around%20that%20axis.%20The%20angular%20position%20can%20be%20treated%20as%20a%20vector%20along%20that%20axis%2C%20with%20its%20sense%20given%20by%20the%20right-hand%20rule%2C%20and%20because%20the%20axis%20never%20changes%2C%20it%20behaves%20like%20a%20number%20with%20a%20sign%3A%20counterclockwise%20positive.%20In%203D%20this%20is%20no%20longer%20true%20for%20finite%20angles%2C%20which%20do%20not%20add%20like%20vectors%3B%20see%20%5BAngular%20velocity%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fangular_velocity_3d.py).%0A%0A%20%20%20%20The%20**angular%20velocity**%20is%20the%20rate%20of%20change%20of%20the%20angular%20position%20with%20respect%20to%20time.%20Over%20a%20finite%20interval%2C%20the%20average%20angular%20velocity%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbar%7B%5Comega%7D%20%3D%20%5Cfrac%7B%5Ctheta(t_2)-%5Ctheta(t_1)%7D%7Bt_2-t_1%7D%20%3D%20%5Cfrac%7B%5CDelta%20%5Ctheta%7D%7B%5CDelta%20t%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20and%20the%20instantaneous%20angular%20velocity%20is%20its%20limit%20as%20the%20interval%20shrinks%20to%20zero%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Comega(t)%20%3D%20%5Cfrac%7Bd%5Ctheta(t)%7D%7Bdt%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20**angular%20acceleration**%20is%20the%20rate%20of%20change%20of%20the%20angular%20velocity%2C%20which%20is%20also%20the%20second-order%20rate%20of%20change%20of%20the%20angular%20position%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Cbar%7B%5Calpha%7D%20%3D%20%5Cfrac%7B%5Comega(t_2)-%5Comega(t_1)%7D%7Bt_2-t_1%7D%20%3D%20%5Cfrac%7B%5CDelta%20%5Comega%7D%7B%5CDelta%20t%7D%0A%20%20%20%20%5Cqquad%20%5Ctext%7Band%7D%20%5Cqquad%0A%20%20%20%20%5Calpha(t)%20%3D%20%5Cfrac%7Bd%5Comega(t)%7D%7Bdt%7D%20%3D%20%5Cfrac%7Bd%5E2%5Ctheta(t)%7D%7Bdt%5E2%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20angular%20velocity%20and%20acceleration%20vectors%20have%20the%20same%20direction%20as%20the%20angular%20position%2C%20perpendicular%20to%20the%20plane%20of%20rotation%2C%20with%20the%20sense%20given%20by%20the%20right-hand%20rule.%0A%0A%20%20%20%20%23%23%23%20The%20antiderivative%0A%0A%20%20%20%20As%20the%20angular%20acceleration%20is%20the%20derivative%20of%20the%20angular%20velocity%2C%20which%20is%20the%20derivative%20of%20the%20angular%20position%2C%20the%20inverse%20operation%20is%20the%20%5Bantiderivative%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FAntiderivative)%2C%20or%20integral%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Ctheta(t)%20%3D%20%5Ctheta_0%20%2B%20%5Cint%20%5Comega(t)%5C%2C%20dt%0A%20%20%20%20%5Cqquad%20%5Ctext%7Band%7D%20%5Cqquad%0A%20%20%20%20%5Comega(t)%20%3D%20%5Comega_0%20%2B%20%5Cint%20%5Calpha(t)%5C%2C%20dt%0A%20%20%20%20%24%24%0A%0A%20%20%20%20These%20are%20the%20same%20relations%20as%20between%20linear%20position%2C%20velocity%20and%20acceleration%20in%20%5BKinematics%20of%20a%20particle%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_particle.py)%2C%20with%20%24%5Ctheta%24%20in%20place%20of%20%24x%24.%20Everything%20learned%20there%20about%20finite%20differences%20carries%20over%2C%20including%20what%20they%20do%20to%20noise.%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%20The%20leg%20during%20walking%0A%0A%20%20%20%20Time%20for%20real%20data.%20Table%20A.1%20of%20Winter%20(2009)%20gives%20the%20coordinates%20of%20eight%20markers%20on%20the%20right%20side%20of%20a%20woman%20walking%20at%20a%20fast%20cadence%3A%2022%20years%20old%2C%2055.7%20kg%2C%20156%20cm%20tall%2C%20115%20steps%20per%20minute.%20The%20coordinates%20are%20in%20centimetres%2C%20in%20the%20sagittal%20plane%2C%20with%20%24x%24%20in%20the%20direction%20of%20walking%20and%20%24y%24%20vertical%2C%20and%20there%20are%20106%20frames%2C%20sampled%20at%20about%2070%20Hz.%20The%20file%20is%20in%20this%20repository's%20%5Bdata%20folder%5D(https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fdata%2FWinterTableA1.txt)%2C%20originally%20from%20%5BWinter's%20book%20student%20site%5D(http%3A%2F%2Fbcs.wiley.com%2Fhe-bcs%2FBooks%3Faction%3Dindex%26bcsId%3D5453%26itemId%3D0470398183).%0A%0A%20%20%20%20Let's%20load%20the%20data%20and%20plot%20the%20markers'%20positions%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(pd%2C%20repo_file)%3A%0A%20%20%20%20data%20%3D%20pd.read_csv(%0A%20%20%20%20%20%20%20%20repo_file('data%2FWinterTableA1.txt')%2C%0A%20%20%20%20%20%20%20%20sep%3D%22%20%22%2C%0A%20%20%20%20%20%20%20%20header%3DNone%2C%0A%20%20%20%20%20%20%20%20skiprows%3D2%2C%0A%20%20%20%20).to_numpy()%0A%20%20%20%20markers%20%3D%20%5B%22RIB%20CAGE%22%2C%20%22HIP%22%2C%20%22KNEE%22%2C%20%22FIBULA%22%2C%20%22ANKLE%22%2C%20%22HEEL%22%2C%20%22MT5%22%2C%20%22TOE%22%5D%0A%0A%20%20%20%20print(%22Columns%3A%20frame%2C%20time%2C%20then%20x%20and%20y%20for%20each%20marker%22)%0A%20%20%20%20print(%22Shape%20of%20the%20data%3A%22%2C%20data.shape)%0A%20%20%20%20return%20data%2C%20markers%0A%0A%0A%40app.cell%0Adef%20_(data%2C%20markers%2C%20plt)%3A%0A%20%20%20%20plt.figure(figsize%3D(10%2C%206))%0A%0A%20%20%20%20_ax%20%3D%20plt.subplot2grid((2%2C%202)%2C%20(0%2C%200))%0A%20%20%20%20_ax.plot(data%5B%3A%2C%201%5D%2C%20data%5B%3A%2C%202%3A%3A2%5D)%0A%20%20%20%20_ax.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Horizontal%20%5Bcm%5D%22)%0A%0A%20%20%20%20_ax%20%3D%20plt.subplot2grid((2%2C%202)%2C%20(0%2C%201))%0A%20%20%20%20_ax.plot(data%5B%3A%2C%201%5D%2C%20data%5B%3A%2C%203%3A%3A2%5D)%0A%20%20%20%20_ax.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Vertical%20%5Bcm%5D%22)%0A%0A%20%20%20%20_ax%20%3D%20plt.subplot2grid((2%2C%202)%2C%20(1%2C%200)%2C%20colspan%3D2)%0A%20%20%20%20_ax.plot(data%5B%3A%2C%202%3A%3A2%5D%2C%20data%5B%3A%2C%203%3A%3A2%5D)%0A%20%20%20%20_ax.set_xlabel(%22Horizontal%20%5Bcm%5D%22)%0A%20%20%20%20_ax.set_ylabel(%22Vertical%20%5Bcm%5D%22)%0A%20%20%20%20_ax.legend(markers%2C%20loc%3D%22center%20left%22%2C%20bbox_to_anchor%3D(1.01%2C%200.5)%2C%20title%3D%22Markers%22)%0A%20%20%20%20plt.suptitle(%0A%20%20%20%20%20%20%20%20%22Table%20A.1%20(Winter%2C%202009)%3A%20female%2C%2022%20yrs%2C%2055.7%20kg%2C%20156%20cm%2C%20%22%0A%20%20%20%20%20%20%20%20%22fast%20cadence%20(115%20steps%2Fmin)%22%2C%0A%20%20%20%20%20%20%20%20y%3D1.0%2C%0A%20%20%20%20%20%20%20%20fontsize%3D14%2C%0A%20%20%20%20)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20We%20will%20follow%20one%20segment%2C%20the%20leg%2C%20with%20the%20same%20definition%20as%20Winter's%20%24%5Ctheta_%7B43%7D%24%20in%20the%20figure%20at%20the%20top%3A%20the%20vector%20from%20the%20ankle%20to%20the%20head%20of%20the%20fibula%2C%20measured%20counterclockwise%20from%20the%20forward%20horizontal.%20A%20vertical%20leg%20is%20then%20at%20%2490%5Eo%24%3B%20a%20leg%20leaning%20forward%2C%20with%20the%20knee%20ahead%20of%20the%20ankle%2C%20is%20below%20%2490%5Eo%24.%0A%0A%20%20%20%20One%20detail%20about%20time.%20The%20time%20column%20is%20rounded%20to%20the%20millisecond%2C%20so%20the%20intervals%20between%20frames%20alternate%20between%200.014%20and%200.015%20s.%20The%20actual%20sampling%20interval%20is%20their%20mean%2C%20about%201%2F70%20s%2C%20and%20that%20is%20what%20we%20use.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%3A%0A%0A%20%20%20%201.%20The%20range%20of%20the%20leg%20angle%20over%20the%20stride.%20Does%20the%20leg%20ever%20lean%20backwards%20past%20the%20vertical%3F%0A%20%20%20%202.%20The%20largest%20angular%20velocity%20of%20the%20leg%2C%20in%20degrees%20per%20second.%20Is%20it%20during%20stance%2C%20with%20the%20foot%20on%20the%20ground%2C%20or%20during%20swing%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(data%2C%20np)%3A%0A%20%20%20%20time%20%3D%20data%5B%3A%2C%201%5D%0A%20%20%20%20dt%20%3D%20np.mean(np.diff(time))%20%20%23%20s%0A%0A%20%20%20%20fibula%20%3D%20data%5B%3A%2C%208%3A10%5D%20%2F%20100%20%20%23%20m%0A%20%20%20%20ankle%20%3D%20data%5B%3A%2C%2010%3A12%5D%20%2F%20100%20%20%23%20m%0A%20%20%20%20leg%20%3D%20fibula%20-%20ankle%0A%0A%20%20%20%20leg_angle%20%3D%20np.unwrap(np.arctan2(leg%5B%3A%2C%201%5D%2C%20leg%5B%3A%2C%200%5D))%20%20%23%20rad%0A%20%20%20%20leg_omega%20%3D%20np.gradient(leg_angle%2C%20dt%2C%20edge_order%3D2)%20%20%23%20rad%2Fs%0A%20%20%20%20leg_alpha%20%3D%20np.gradient(leg_omega%2C%20dt%2C%20edge_order%3D2)%20%20%23%20rad%2Fs2%0A%0A%20%20%20%20print(f%22Sampling%20interval%3A%20%7Bdt%3A.4f%7D%20s%20(%7B1%20%2F%20dt%3A.1f%7D%20Hz)%22)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22Leg%20angle%3A%20from%20%7Bnp.rad2deg(leg_angle.min())%3A.1f%7D%20to%20%22%0A%20%20%20%20%20%20%20%20f%22%7Bnp.rad2deg(leg_angle.max())%3A.1f%7D%20degrees%22%0A%20%20%20%20)%0A%20%20%20%20_i%20%3D%20np.argmax(leg_omega)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22Largest%20angular%20velocity%3A%20%7Bleg_omega%5B_i%5D%3A.2f%7D%20rad%2Fs%20%22%0A%20%20%20%20%20%20%20%20f%22(%7Bnp.rad2deg(leg_omega%5B_i%5D)%3A.0f%7D%20degrees%2Fs)%20at%20t%20%3D%20%7Btime%5B_i%5D%3A.2f%7D%20s%22%0A%20%20%20%20)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22Angular%20acceleration%3A%20from%20%7Bleg_alpha.min()%3A.0f%7D%20to%20%22%0A%20%20%20%20%20%20%20%20f%22%7Bleg_alpha.max()%3A.0f%7D%20rad%2Fs2%22%0A%20%20%20%20)%0A%20%20%20%20return%20dt%2C%20leg%2C%20leg_alpha%2C%20leg_angle%2C%20leg_omega%2C%20time%0A%0A%0A%40app.cell%0Adef%20_(leg_alpha%2C%20leg_angle%2C%20leg_omega%2C%20np%2C%20plt%2C%20time)%3A%0A%20%20%20%20_fig%2C%20_axs%20%3D%20plt.subplots(3%2C%201%2C%20figsize%3D(9%2C%207)%2C%20sharex%3DTrue)%0A%20%20%20%20_axs%5B0%5D.plot(time%2C%20np.rad2deg(leg_angle)%2C%20color%3D%22tab%3Ablue%22%2C%20linewidth%3D2)%0A%20%20%20%20_axs%5B0%5D.axhline(90%2C%20color%3D%220.5%22%2C%20linestyle%3D%22%3A%22)%0A%20%20%20%20_axs%5B0%5D.set_ylabel(%22Angle%20%5B%24%5Eo%24%5D%22)%0A%20%20%20%20_axs%5B1%5D.plot(time%2C%20leg_omega%2C%20color%3D%22tab%3Agreen%22%2C%20linewidth%3D2)%0A%20%20%20%20_axs%5B1%5D.set_ylabel(r%22%24%5Comega%24%20%5Brad%2Fs%5D%22)%0A%20%20%20%20_axs%5B2%5D.plot(time%2C%20leg_alpha%2C%20color%3D%22tab%3Ared%22%2C%20linewidth%3D2)%0A%20%20%20%20_axs%5B2%5D.set_ylabel(r%22%24%5Calpha%24%20%5Brad%2Fs%24%5E2%24%5D%22)%0A%20%20%20%20_axs%5B2%5D.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20for%20_ax%20in%20_axs%3A%0A%20%20%20%20%20%20%20%20_ax.axhline(0%2C%20color%3D%22k%22%2C%20linewidth%3D0.5)%0A%20%20%20%20%20%20%20%20for%20_toe_off%20in%20(time%5B0%5D%2C%20time%5B69%5D)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_ax.axvline(_toe_off%2C%20color%3D%220.5%22%2C%20linestyle%3D%22--%22%2C%20linewidth%3D1)%0A%20%20%20%20_axs%5B0%5D.text(time%5B0%5D%20%2B%200.02%2C%20100%2C%20%22toe-off%22%2C%20fontsize%3D11)%0A%20%20%20%20_axs%5B0%5D.text(time%5B69%5D%20%2B%200.02%2C%20100%2C%20%22toe-off%22%2C%20fontsize%3D11)%0A%20%20%20%20_axs%5B0%5D.set_title(%22Leg%20(shank)%20angle%20during%20walking%2C%20Winter's%20Table%20A.1%22)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20dashed%20lines%20mark%20two%20consecutive%20toe-offs%20of%20the%20right%20foot%2C%20frames%201%20and%2070%2C%20so%20the%20plot%20shows%20one%20full%20stride%20and%20the%20beginning%20of%20the%20next.%0A%0A%20%20%20%20Right%20after%20toe-off%20the%20leg%20swings%20forward%20fast.%20It%20rotates%20counterclockwise%20from%20about%20%2430%5Eo%24%2C%20leaning%20far%20forward%2C%20to%20about%20%24115%5Eo%24%2C%20past%20the%20vertical%2C%20with%20the%20ankle%20ahead%20of%20the%20knee%20as%20the%20foot%20reaches%20for%20the%20ground.%20Its%20angular%20velocity%20peaks%20at%20about%207.5%20rad%2Fs%2C%20over%20%24400%5Eo%24%20per%20second.%20Then%20the%20foot%20lands%2C%20and%20during%20stance%20the%20body%20passes%20over%20it%3A%20the%20leg%20rotates%20back%20slowly%2C%20clockwise%2C%20until%20the%20next%20toe-off.%0A%0A%20%20%20%20Now%20look%20at%20the%20bottom%20panel.%20The%20angle%20is%20smooth%2C%20the%20angular%20velocity%20is%20still%20reasonably%20smooth%2C%20and%20the%20angular%20acceleration%20is%20rough%2C%20with%20spikes%20beyond%20100%20rad%2Fs%C2%B2.%20The%20leg%20is%20not%20really%20jerking%20back%20and%20forth%20like%20that.%20Each%20differentiation%20amplifies%20whatever%20small%20errors%20the%20coordinates%20carry%2C%20as%20in%20%5BKinematics%20of%20a%20particle%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fkinematics_particle.py)%2C%20and%20the%20second%20one%20amplifies%20them%20twice.%20Before%20angular%20accelerations%20from%20marker%20data%20are%20used%20for%20anything%2C%20such%20as%20the%20joint%20moments%20of%20an%20inverse%20dynamics%20analysis%2C%20the%20coordinates%20are%20low-pass%20filtered%3B%20see%20%5BData%20filtering%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fdata_filtering.py).%0A%0A%20%20%20%20**Guiding%20questions%202.**%0A%0A%20%20%20%201.%20The%20dotted%20line%20marks%20the%20vertical%20leg.%20How%20many%20times%20per%20stride%20does%20the%20leg%20pass%20through%20it%2C%20and%20what%20is%20happening%20in%20the%20gait%20cycle%20each%20time%3F%0A%20%20%20%202.%20Why%20is%20the%20angular%20velocity%20so%20much%20larger%20in%20swing%20than%20in%20stance%3F%0A%20%20%20%203.%20The%20leg%20angle%20stays%20between%20about%20%2430%5Eo%24%20and%20%24116%5Eo%24%2C%20far%20from%20%24%5Cpm%20180%5Eo%24.%20Did%20%60unwrap%60%20change%20anything%20here%3F%20For%20which%20segment%20of%20the%20lower%20limb%2C%20and%20with%20which%20choice%20of%20direction%20for%20its%20vector%2C%20would%20it%20be%20needed%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%20Relationship%20between%20linear%20and%20angular%20kinematics%0A%0A%20%20%20%20Consider%20a%20particle%20rotating%20around%20a%20point%20at%20a%20fixed%20distance%20%24r%24%2C%20that%20is%2C%20in%20circular%20motion.%20As%20the%20particle%20moves%20along%20the%20circle%20it%20travels%20an%20arc%20of%20length%20%24s%24%2C%20and%20its%20angular%20position%20is%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Ctheta%20%3D%20%5Cfrac%7Bs%7D%7Br%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20which%20is%20in%20fact%20the%20definition%20of%20the%20radian%3A%0A%0A%20%20%20%20%3Cfigure%20aria-describedby%3D%22figure-caption-3%22%3E%3Ccenter%3E%3Cimg%20src%3D%22https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F3%2F3d%2FRadian_cropped_color.svg%22%20width%3D200%20alt%3D%22radian%22%2F%3E%3C%2Fcenter%3E%3C%2Ffigure%3E%0A%0A%20%20%20%20%3Cspan%20id%3D%22figure-caption-3%22%20class%3D%22figure-caption%22%20style%3D%22display%3Ablock%3Btext-align%3Acenter%3Bfont-style%3Aitalic%22%3EFigure.%20An%20arc%20of%20a%20circle%20with%20the%20same%20length%20as%20the%20radius%20of%20that%20circle%20corresponds%20to%20an%20angle%20of%201%20radian%20(%3Ca%20href%3D%22https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FRadian%22%3Eimage%20from%20Wikipedia%3C%2Fa%3E).%3C%2Fspan%3E%0A%0A%20%20%20%20The%20distance%20travelled%20by%20the%20particle%20is%20therefore%20the%20arc%20length%20%24s%20%3D%20r%5Ctheta%24%2C%20and%20because%20the%20radius%20is%20constant%2C%20the%20speed%20and%20the%20rate%20of%20change%20of%20the%20speed%20follow%20directly%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20v%20%3D%20%5Cfrac%7Bds%7D%7Bdt%7D%20%3D%20r%5Cfrac%7Bd%5Ctheta%7D%7Bdt%7D%20%3D%20r%5Comega%0A%20%20%20%20%5Cqquad%20%5Ctext%7Band%7D%20%5Cqquad%0A%20%20%20%20a_t%20%3D%20%5Cfrac%7Bdv%7D%7Bdt%7D%20%3D%20r%5Cfrac%7Bd%5Comega%7D%7Bdt%7D%20%3D%20r%5Calpha%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20subscript%20on%20%24a_t%24%20matters.%20%24r%5Calpha%24%20is%20the%20**tangential**%20acceleration%2C%20the%20part%20that%20changes%20the%20particle's%20speed%2C%20and%20it%20is%20not%20the%20whole%20acceleration.%20A%20particle%20moving%20on%20a%20circle%20at%20constant%20speed%20has%20%24%5Calpha%20%3D%200%24%20and%20is%20still%20accelerating%2C%20because%20the%20direction%20of%20its%20velocity%20keeps%20turning.%20That%20is%20the%20**normal**%2C%20or%20centripetal%2C%20acceleration%2C%20pointing%20to%20the%20centre%20of%20the%20circle%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20a_n%20%3D%20%5Cfrac%7Bv%5E2%7D%7Br%7D%20%3D%20%5Comega%5E2%20r%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20general%20form%20of%20this%20split%2C%20for%20any%20curved%20path%2C%20is%20the%20subject%20of%20%5BPath%20frame%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fpath_frame.py).%20Note%20also%20that%20all%20these%20relations%20need%20%24%5Ctheta%24%2C%20%24%5Comega%24%20and%20%24%5Calpha%24%20in%20radians%3A%20%24r%5Comega%24%20with%20%24%5Comega%24%20in%20degrees%20per%20second%20is%20not%20a%20speed.%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%20Checking%20%24v%20%3D%20r%5Comega%24%20on%20the%20leg%0A%0A%20%20%20%20The%20fibula%20head%20and%20the%20ankle%20are%20two%20points%20of%20the%20same%20rigid%20bone%2C%20so%20relative%20to%20the%20ankle%2C%20the%20fibula%20head%20moves%20on%20a%20circle%20of%20radius%20equal%20to%20the%20length%20of%20the%20leg%2C%20%24L%24.%20Its%20speed%20relative%20to%20the%20ankle%20should%20then%20be%20%24L%5C%2C%7C%5Comega%7C%24.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20whether%20the%20two%20will%20agree%2C%20and%20whether%20%24L%24%20will%20be%20constant.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(dt%2C%20leg%2C%20leg_omega%2C%20np%2C%20plt%2C%20time)%3A%0A%20%20%20%20leg_length%20%3D%20np.linalg.norm(leg%2C%20axis%3D1)%20%20%23%20m%0A%20%20%20%20_speed_rel%20%3D%20np.linalg.norm(np.gradient(leg%2C%20dt%2C%20axis%3D0%2C%20edge_order%3D2)%2C%20axis%3D1)%0A%0A%20%20%20%20_fig%2C%20_axs%20%3D%20plt.subplots(2%2C%201%2C%20figsize%3D(9%2C%205.5)%2C%20sharex%3DTrue)%0A%20%20%20%20_axs%5B0%5D.plot(time%2C%20_speed_rel%2C%20color%3D%22tab%3Ablue%22%2C%20linewidth%3D3%2C%20label%3D%22measured%20relative%20speed%22)%0A%20%20%20%20_axs%5B0%5D.plot(time%2C%20leg_length%20*%20np.abs(leg_omega)%2C%20color%3D%22tab%3Aorange%22%2C%20linewidth%3D2%2C%20label%3Dr%22%24L%5C%2C%7C%5Comega%7C%24%22)%0A%20%20%20%20_axs%5B0%5D.set_ylabel(%22Speed%20%5Bm%2Fs%5D%22)%0A%20%20%20%20_axs%5B0%5D.legend(loc%3D%22upper%20center%22)%0A%20%20%20%20_axs%5B1%5D.plot(time%2C%20100%20*%20leg_length%2C%20color%3D%22k%22%2C%20linewidth%3D2)%0A%20%20%20%20_axs%5B1%5D.set_ylabel(%22Leg%20length%20L%20%5Bcm%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%0A%20%20%20%20_i%20%3D%20np.argmax(leg_omega)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22Leg%20length%3A%20from%20%7B100%20*%20leg_length.min()%3A.1f%7D%20to%20%22%0A%20%20%20%20%20%20%20%20f%22%7B100%20*%20leg_length.max()%3A.1f%7D%20cm%22%0A%20%20%20%20)%0A%20%20%20%20print(%0A%20%20%20%20%20%20%20%20f%22At%20the%20peak%20angular%20velocity%3A%20measured%20%7B_speed_rel%5B_i%5D%3A.2f%7D%20m%2Fs%2C%20%22%0A%20%20%20%20%20%20%20%20f%22L%7Comega%7C%20%3D%20%7Bleg_length%5B_i%5D%20*%20leg_omega%5B_i%5D%3A.2f%7D%20m%2Fs%2C%20%22%0A%20%20%20%20%20%20%20%20f%22centripetal%20acceleration%20omega%5E2%20L%20%3D%20%7Bleg_length%5B_i%5D%20*%20leg_omega%5B_i%5D%20**%202%3A.1f%7D%20m%2Fs2%22%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%20The%20two%20curves%20agree%20almost%20everywhere%2C%20with%20a%20median%20difference%20of%20a%20few%20millimetres%20per%20second%3A%20the%20relative%20speed%20of%20the%20fibula%20head%20really%20is%20%24L%5Comega%24.%20At%20the%20peak%2C%20while%20the%20leg%20rotates%20at%207.5%20rad%2Fs%2C%20the%20fibula%20head%20also%20has%20a%20centripetal%20acceleration%20towards%20the%20ankle%20of%20%24%5Comega%5E2%20L%20%5Capprox%2019%5C%3B%5Cmathrm%7Bm%2Fs%5E2%7D%24%2C%20about%20twice%20%24g%24%2C%20just%20from%20the%20leg's%20rotation.%0A%0A%20%20%20%20Yet%20the%20bottom%20panel%20says%20the%20%22rigid%22%20leg%20changes%20length%20by%20almost%203%20cm.%20The%20bone%20does%20not%20stretch.%20Markers%20on%20the%20skin%20slide%20over%20the%20bone%2C%20the%20digitized%20coordinates%20carry%20errors%2C%20and%20the%20leg%20is%20not%20perfectly%20in%20the%20plane%20of%20the%20camera.%20All%20of%20these%20show%20up%20as%20motion%20*along*%20the%20segment%2C%20which%20%24v%20%3D%20r%5Comega%24%20cannot%20produce%2C%20at%20up%20to%200.4%20m%2Fs.%20Why%20does%20it%20barely%20show%20in%20the%20top%20panel%3F%20Because%20motion%20along%20the%20segment%20is%20perpendicular%20to%20the%20rotational%20motion%2C%20so%20the%20two%20add%20in%20quadrature%3A%20the%20measured%20speed%20is%20%24%5Csqrt%7Bv_r%5E2%20%2B%20(L%5Comega)%5E2%7D%24.%20Next%20to%20a%20fast%20rotation%20a%20small%20%24v_r%24%20disappears.%20Only%20where%20the%20rotation%20is%20slow%2C%20during%20stance%2C%20as%20near%200.58%20s%2C%20does%20the%20measured%20speed%20rise%20visibly%20above%20%24L%7C%5Comega%7C%24.%0A%0A%20%20%20%20**Challenge%202.**%20Split%20the%20relative%20velocity%20of%20the%20fibula%20head%20into%20its%20component%20along%20the%20leg%20and%20its%20component%20perpendicular%20to%20it%2C%20using%20the%20dot%20product%20with%20the%20leg's%20versor%20and%20with%20that%20versor%20rotated%20by%20%2490%5Eo%24.%20Which%20component%20does%20%24v%20%3D%20r%5Comega%24%20predict%3F%20Plot%20the%20other%20one%20and%20decide%3A%20does%20it%20look%20like%20a%20physical%20movement%20or%20like%20noise%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**Exercise%203.**%20A%20point%200.4%20m%20from%20a%20fixed%20axis%20rotates%20at%203%20rad%2Fs%20with%20angular%20acceleration%202%20rad%2Fs%C2%B2.%20Find%20tangential%20speed%20and%20both%20accelerations.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Worked%20solution%20%E2%80%94%20Exercise%203%0A%0A%20%20%20%20%24v%3Dr%5Comega%3D1.2%24%20m%2Fs%2C%20%24a_t%3Dr%5Calpha%3D0.8%24%20m%2Fs%C2%B2%20and%20%24a_n%3Dr%5Comega%5E2%3D3.6%24%20m%2Fs%C2%B2%20inward.%20Constant%20angular%20speed%20would%20remove%20only%20%24a_t%24.%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%20Checkpoint%20questions%0A%0A%20%20%20%20Pause%20here%20before%20the%20problems.%0A%0A%20%20%20%201.%20Go%20back%20to%20the%20two%20knee%20angles%20you%20wrote%20down%20in%20Challenge%200.%20State%20the%20convention%20behind%20each%20one%20precisely%20enough%20that%20someone%20else%20would%20compute%20the%20same%20numbers.%0A%20%20%20%202.%20Give%20a%20segment%20orientation%20for%20which%20%60arctan%60%20of%20the%20ratio%20of%20the%20differences%20returns%20the%20wrong%20angle%2C%20and%20say%20what%20information%20it%20threw%20away.%0A%20%20%20%203.%20What%20is%20the%20lowest%20sampling%20rate%20at%20which%20%60unwrap%60%20could%20correctly%20follow%20the%20leg's%20swing%2C%20at%20its%20peak%20of%20about%20%24430%5Eo%24%20per%20second%3F%20Would%20you%20ever%20sample%20that%20slowly%3F%0A%20%20%20%204.%20When%20does%20it%20matter%20that%20%60angle_between%60%20is%20unsigned%3F%20Name%20one%20joint%20and%20one%20movement%20where%20losing%20the%20sign%20would%20lead%20to%20a%20wrong%20clinical%20conclusion.%0A%20%20%20%205.%20From%20marker%20data%20you%20computed%20%24%5Ctheta%24%2C%20%24%5Comega%24%20and%20%24%5Calpha%24.%20Which%20do%20you%20trust%20the%20least%2C%20and%20why%3F%0A%20%20%20%206.%20A%20gymnast%20lets%20go%20of%20the%20bar%20at%20the%20bottom%20of%20a%20giant%20circle.%20In%20which%20direction%20is%20the%20velocity%20of%20the%20gymnast's%20centre%20of%20mass%20at%20the%20instant%20of%20release%2C%20and%20what%20is%20its%20magnitude%20in%20terms%20of%20%24%5Comega%24%20and%20%24r%24%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.%20A%20gymnast%20performs%20giant%20circles%20around%20the%20horizontal%20bar%20(with%20bar%20height%20%24h_b%24%20above%20the%20landing%20surface)%20at%20a%20constant%20rate%20of%20one%20circle%20every%202%20s%2C%20and%20the%20gymnast's%20centre%20of%20mass%20is%201%20m%20from%20the%20bar.%20At%20the%20lowest%20point%2C%20exactly%20beneath%20the%20bar%2C%20the%20gymnast%20releases%20it%2C%20moves%20forward%2C%20and%20lands%20standing%20on%20the%20ground.%3Cbr%3E%0A%20%20%20%20%20%20%20a.%20Calculate%20the%20angular%20and%20linear%20velocity%20of%20the%20gymnast's%20centre%20of%20mass%20at%20the%20point%20of%20release.%3Cbr%3E%0A%20%20%20%20%20%20%20b.%20Calculate%20the%20horizontal%20distance%20travelled%20by%20the%20gymnast's%20centre%20of%20mass%2C%20stating%20its%20landing%20height%20%24h_l%24.%20Do%20not%20identify%20the%20standing%20centre%20of%20mass%20with%20ground%20level.%0A%0A%20%20%20%202.%20With%20the%20data%20from%20Table%20A.1%20of%20Winter%20(2009)%2C%20already%20loaded%20above%20in%20%60data%60%2C%20and%20the%20convention%20for%20the%20sagittal%20joint%20angles%20of%20the%20lower%20limb%20in%20the%20figure%20at%20the%20top%3A%3Cbr%3E%0A%20%20%20%20%20%20%20a.%20Calculate%20and%20plot%20the%20angles%20of%20the%20foot%20and%20thigh%20segments%20(the%20leg%20was%20done%20above).%3Cbr%3E%0A%20%20%20%20%20%20%20b.%20Calculate%20and%20plot%20the%20angles%20of%20the%20ankle%2C%20knee%20and%20hip%20joints.%3Cbr%3E%0A%20%20%20%20%20%20%20c.%20Calculate%20and%20plot%20the%20angular%20velocities%20and%20accelerations%20of%20the%20joint%20angles%20calculated%20in%20b.%3Cbr%3E%0A%20%20%20%20%20%20%20d.%20Compare%20the%20ankle%20angle%20using%20the%20two%20different%20conventions%20described%20by%20Winter%20(2009)%2C%20that%20is%2C%20defining%20the%20foot%20segment%20with%20the%20MT5%20or%20with%20the%20TOE%20marker.%3Cbr%3E%0A%20%20%20%20%20%20%20e.%20Knowing%20that%20a%20stride%20corresponds%20to%20the%20data%20between%20frames%201%20and%2070%20(two%20subsequent%20toe-offs%20of%20the%20right%20foot)%2C%20can%20you%20suggest%20a%20way%20to%20determine%20a%20stride%20automatically%3F%20Hint%3A%20look%20at%20the%20vertical%20displacement%20and%20acceleration%20of%20the%20heel%20marker.%0A%0A%20%20%20%203.%20Recompute%20the%20angular%20velocity%20and%20acceleration%20of%20the%20leg%20keeping%20only%20every%20second%20frame%20of%20the%20data%20(about%2035%20Hz).%20Compare%20with%20the%20results%20at%2070%20Hz.%20Which%20looks%20smoother%3F%20Which%20is%20more%20accurate%2C%20and%20how%20could%20you%20tell%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Final%20answers%20to%20the%20problems%0A%0A%20%20%20%201.%20(a)%20%24%7C%5Comega%7C%3D%5Cpi%24%20rad%2Fs%20and%20%24v%3D%5Cpi%24%20m%2Fs%2C%20horizontal%20at%20release.%20(b)%20%24R%3D%5Cpi%5Csqrt%7B2(h_b-1-h_l)%2Fg%7D%24%20m%20when%20%24h_b-1%3Eh_l%24.%20For%20the%20explicitly%20assumed%20heights%20%24h_b%3D2.8%24%20m%20and%20%24h_l%3D1.0%24%20m%2C%20%24R%3D1.269%24%20m.%20A%20unique%20range%20cannot%20be%20obtained%20without%20a%20centre-of-mass%20landing%20height.%0A%20%20%20%202.%20With%20each%20segment%20orientation%20defined%20by%20the%20directed%20marker%20pair%2C%20%24%5Ctheta%3D%5Coperatorname%7Batan2%7D(%5CDelta%20y%2C%5CDelta%20x)%24.%20Joint%20rotations%20are%20signed%20differences%20of%20adjacent%20unwrapped%20orientations%2C%20plus%20the%20stated%20anatomical%20zero%20offset%3B%20%24%5Comega%3Dd%5Ctheta%2Fdt%24%20and%20%24%5Calpha%3Dd%5E2%5Ctheta%2Fdt%5E2%24.%20MT5%20and%20TOE%20definitions%20give%20different%20foot%20orientation%20offsets%2C%20so%20they%20give%20different%20ankle%20curves%20without%20any%20change%20in%20motion.%20Successive%20equivalent%20heel%20events%20can%20delimit%20a%20cycle%2C%20but%20a%20low%20heel-height%20threshold%20alone%20cannot%20distinguish%20all%20toe-off%2Fcontact%20events%3B%20check%20velocity%2C%20acceleration%20and%20the%20known%20frames%201%E2%80%9370.%0A%20%20%20%203.%20Subsampling%20often%20makes%20differentiated%20noise%20look%20smoother%20while%20reducing%20temporal%20resolution.%20It%20can%20miss%20peaks%20and%20shift%20events%3B%20a%20smoother%20curve%20is%20not%20proof%20of%20greater%20accuracy.%20A%20known%20trajectory%2C%20independent%20measurement%20or%20sensitivity%20analysis%20is%20needed%20to%20decide%20accuracy.%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_(data%2C%20dt%2C%20mo%2C%20np%2C%20plt)%3A%0A%20%20%20%20_hip%2C%20_knee%2C%20_ankle%2C%20_heel%2C%20_mt5%2C%20_toe%20%3D%20%5Bdata%5B%3A%2C%20_a%3A_a%2B2%5D%20for%20_a%20in%20%5B4%2C%206%2C%2010%2C%2012%2C%2014%2C%2016%5D%5D%0A%20%20%20%20def%20_angle(_v)%3A%0A%20%20%20%20%20%20%20%20return%20np.unwrap(np.arctan2(_v%5B%3A%2C%201%5D%2C%20_v%5B%3A%2C%200%5D))%0A%20%20%20%20_thigh%20%3D%20_angle(_hip%20-%20_knee)%0A%20%20%20%20_leg%20%3D%20_angle(data%5B%3A%2C%208%3A10%5D%20-%20_ankle)%0A%20%20%20%20_foot%20%3D%20_angle(_heel%20-%20_mt5)%0A%20%20%20%20_foot_toe%20%3D%20_angle(_heel%20-%20_toe)%0A%20%20%20%20_trunk%20%3D%20_angle(data%5B%3A%2C%202%3A4%5D%20-%20_hip)%0A%20%20%20%20_angles%20%3D%20np.column_stack((_thigh%20-%20_leg%2C%20_leg%20-%20_foot%20%2B%20np.pi%2F2%2C%20_trunk%20-%20_thigh))%0A%20%20%20%20_fig%2C%20_axs%20%3D%20plt.subplots(2%2C%202%2C%20figsize%3D(10%2C%207))%0A%20%20%20%20_axs%5B0%2C0%5D.plot(data%5B%3A%2C1%5D%2C%20np.degrees(np.c_%5B_thigh%2C_leg%2C_foot%5D))%0A%20%20%20%20_axs%5B0%2C0%5D.legend(%5B%22thigh%22%2C%20%22leg%22%2C%20%22foot%20(MT5%E2%80%93heel)%22%5D)%0A%20%20%20%20for%20_ax%2C%20_values%2C%20_unit%20in%20zip(%5B_axs%5B0%2C1%5D%2C_axs%5B1%2C0%5D%2C_axs%5B1%2C1%5D%5D%2C%20%5B_angles%2Cnp.gradient(_angles%2Cdt%2Caxis%3D0%2Cedge_order%3D2)%2Cnp.gradient(np.gradient(_angles%2Cdt%2Caxis%3D0%2Cedge_order%3D2)%2Cdt%2Caxis%3D0%2Cedge_order%3D2)%5D%2C%20%5B%22deg%22%2C%22deg%2Fs%22%2C%22deg%2Fs%C2%B2%22%5D)%3A%0A%20%20%20%20%20%20%20%20_ax.plot(data%5B%3A%2C1%5D%2Cnp.degrees(_values))%0A%20%20%20%20%20%20%20%20_ax.set(xlabel%3D%22Time%20%5Bs%5D%22%2Cylabel%3D_unit)%0A%20%20%20%20%20%20%20%20_ax.legend(%5B%22knee%22%2C%20%22ankle%22%2C%20%22hip%22%5D)%0A%20%20%20%20_axs%5B0%2C0%5D.set(xlabel%3D%22Time%20%5Bs%5D%22%2Cylabel%3D%22Segment%20angle%20%5Bdeg%5D%22)%0A%20%20%20%20_fig.tight_layout()%0A%20%20%20%20_note%20%3D%20mo.md(%22Final%20curves%20with%20directed%20distal-to-proximal%20thigh%2Fleg%20axes%20and%20MT5-to-heel%20foot%20axis%3B%20joint%20definitions%20are%20knee%20%3D%20thigh%20%E2%88%92%20leg%2C%20ankle%20%3D%20leg%20%E2%88%92%20foot%20%2B%2090%C2%B0%2C%20hip%20%3D%20trunk%20%E2%88%92%20thigh.%20The%20alternative%20TOE-to-heel%20foot%20axis%20changes%20the%20ankle%20angle%20by%20%22%20%2B%20f%22%7Bnp.degrees((_foot-_foot_toe).min())%3A.2f%7D%20to%20%7Bnp.degrees((_foot-_foot_toe).max())%3A.2f%7D%C2%B0.%20These%20explicit%20definitions%20fix%20the%20signs%20and%20anatomical%20zero%20offsets.%22)%0A%20%20%20%20_problem_plot%20%3D%20mo.accordion(%7B%22Final%20plots%20%E2%80%94%20Winter%20gait%20problem%22%3A%20mo.vstack(%5B_note%2C%20mo.as_html(_fig)%5D)%7D%2C%20expanded%3DFalse)%0A%20%20%20%20plt.close(_fig)%0A%20%20%20%20_problem_plot%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Go%20deeper%0A%0A%20%20%20%20-%20Read%20pages%20718%E2%80%93742%20of%20chapter%2015%20of%20%5BRuina%20and%20Pratap's%20book%5D(https%3A%2F%2Fruina.tam.cornell.edu%2FBook%2Findex.html)%20about%20the%20circular%20motion%20of%20a%20particle.%0A%20%20%20%20-%20%5BPath%20frame%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fpath_frame.py)%20%E2%80%94%20the%20tangential%20and%20normal%20accelerations%20for%20any%20curved%20path.%0A%20%20%20%20-%20%5BScalar%20and%20vector%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fscalar_vector.py)%20%E2%80%94%20the%20dot%20and%20cross%20products%20behind%20%60angle_between%60.%0A%20%20%20%20-%20%5BData%20filtering%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fdata_filtering.py)%20%E2%80%94%20what%20to%20do%20before%20differentiating%20measured%20angles.%0A%20%20%20%20-%20%5BAngular%20velocity%20in%203D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fangular_velocity_3d.py)%20%E2%80%94%20what%20changes%20when%20the%20plane%20is%20not%20fixed.%0A%0A%20%20%20%20%23%23%23%20Video%20lectures%20on%20the%20Internet%0A%0A%20%20%20%20-%20Khan%20Academy%3A%20%5BUniform%20Circular%20Motion%20Introduction%5D(https%3A%2F%2Fwww.khanacademy.org%2Fscience%2Fap-physics-1%2Fap-centripetal-force-and-gravitation)%0A%20%20%20%20-%20%5BAngular%20Motion%20and%20Torque%5D(https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DjNc2SflUl9U)%0A%20%20%20%20-%20%5BRotational%20Motion%20Physics%2C%20Basic%20Introduction%2C%20Angular%20Velocity%20%26%20Tangential%20Acceleration%5D(https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DWQ9AH2S8B6Y)%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-%20Ruina%20A%2C%20Pratap%20R%20(2019)%20%5BIntroduction%20to%20Statics%20and%20Dynamics%5D(https%3A%2F%2Fruina.tam.cornell.edu%2FBook%2Findex.html).%20Oxford%20University%20Press.%0A%0A%20%20%20%20-%20Winter%20DA%20(2009)%20%5BBiomechanics%20and%20Motor%20Control%20of%20Human%20Movement%5D(https%3A%2F%2Fbooks.google.com.br%2Fbooks%3Fid%3D_bFHL08IWfwC).%204th%20edition.%20Hoboken%2C%20USA%3A%20Wiley.%0A%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
90e3b552455583b838439cb8ebbcff2f