%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%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()%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%20Kistler%20force%20plate%20calculation%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%20notebook%0A%0A%20%20%20%20Start%20with%20voltages%20and%20predict%20the%20force%20before%20looking%20at%20the%20plot.%20Keep%20track%20of%20channel%20order%2C%20amplifier%20range%2C%20coordinates%20and%20units%20through%20each%20calculation.%20The%20worked%20exercises%20explain%20the%20transformations%3B%20the%20final%20problems%20let%20you%20check%20them%20independently.%0A%0A%20%20%20%20%23%23%20Opening%20challenge%0A%0A%20%20%20%20Two%20laboratories%20record%20the%20same%20force%20using%20different%20amplifier%20ranges.%20Their%20voltages%20differ.%20Should%20their%20calibrated%20forces%20differ%20too%3F%20What%20additional%20information%20turns%20eight%20voltage%20channels%20into%20a%20force%2C%20a%20centre%20of%20pressure%20and%20a%20free%20moment%3F%0A%0A%20%20%20%20%23%23%20Setup%0A%0A%20%20%20%20The%20example%20uses%20NumPy%2C%20Matplotlib%2C%20the%20bundled%20%60kistler_fp_data.txt%60%20recording%20and%20%60kistler_fp_cal%60.%20The%20first%20data%20column%20is%20time%3B%20the%20remaining%20eight%20columns%20follow%20the%20sensor%20convention%20in%20the%20retained%20figure.%20The%20example%20selects%20horizontal%20range%200%20and%20vertical%20range%201%20from%20the%20supplied%20historical%20calibration.%20Check%20those%20choices%20against%20the%20actual%20acquisition%20whenever%20you%20use%20new%20data.%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%20In%20order%20to%20get%20proper%20signals%20of%20a%20Kistler%20force%20plate%2C%20we%20have%20to%20calibrate%20the%20acquired%20data%20according%20to%20the%20factory%20calibration%20(i.e.%2C%20transform%20the%20recorded%20values%20in%20volts%20of%20the%208%20channels%20to%20values%20in%20newtons%20for%20fx12%2C%20fx34%2C%20fy14%2C%20fy23%2C%20fz1%2C%20fz2%2C%20fz3%2C%20fz4)%20and%20then%20calculate%20the%20resultant%20forces%20(Fx%2C%20Fy%2C%20Fz)%2C%20resultant%20moments%20of%20force%20(Mx%2C%20My%2C%20Mz)%2C%20and%20center%20of%20pressure%20(COPx%2C%20COPy)%20quantities%20(see%20figure%20below%20for%20the%20convention%20used).%0A%0A%20%20%20%20%3Cdiv%20class%3D'center-align'%3E%3Cfigure%20aria-describedby%3D%22figure-caption-1%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fimages%2FKistlerForcePlate.png%3Fraw%3D1%22alt%3D%22Kistler%20force%20plate%20and%20its%20coordinate%20system%20convention%22%2F%3E%3C%2Ffigure%3E%3C%2Fdiv%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.%20Kistler%20force%20plate%20and%20its%20coordinate%20system%20convention%20(from%20%5BKistler%20Force%20Plate%20Formulae%5D(https%3A%2F%2Fisbweb.org%2Fsoftware%2Fmovanal%2Fvaughan%2Fkistler.pdf)).%3C%2Fspan%3E%0A%0A%20%20%20%20The%20function%20%60kistler_fp_cal.py%60%20performs%20such%20calculations%20for%20the%20Kistler%20force%20plates%20of%20the%20BMClab%2C%20and%20its%20defaults%20belong%20to%20one%20specific%20plate%2Famplifier%20setup.%20Another%20plate%20requires%20its%20own%20channel%20order%2C%20sensitivity%20table%2C%20amplifier%20ranges%2C%20geometry%20and%20applicable%20COP%20correction%3B%20these%20values%20are%20not%20interchangeable.%20The%20function%20signature%20is%3A%3Cbr%3E%0A%20%20%20%20%60%60%60python%0A%20%20%20%20grf%2C%20cop%20%3D%20kistler_fp_cal(data%2C%20S_matrix%3DNone%2C%20fxfy_range%3D0%2C%20fz_range%3D0%2C%20origin%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fp_type%3D3%2C%20show%3DFalse%2C%20axs%3DNone)%0A%20%20%20%20%60%60%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)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Exercise%201%20%E2%80%94%20sensitivity.**%20A%20channel%20has%20sensitivity%202%20mV%2FN%20and%20records%200.020%20V.%20What%20force%20does%20it%20represent%3F%20What%20goes%20wrong%20if%20volts%20are%20treated%20as%20millivolts%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Worked%20solution%20%E2%80%94%20Exercise%201%20%E2%80%94%20sensitivity%0A%0A%20%20%20%20Convert%20first%3A%20%240.020%5C%2C%5Cmathrm%7BV%7D%3D20%5C%2C%5Cmathrm%7BmV%7D%24%2C%20so%20%24F%3D20%2F2%3D10%24%20N.%20Omitting%20the%20conversion%20gives%20a%20result%201000%20times%20too%20small.%20The%20helper%20applies%20%601000%20*%20volts%20%2F%20sensitivity%60.%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%20Example%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%20Follow%20the%20mechanics%0A%0A%20%20%20%20The%20four%20vertical%20channels%20add%20to%20%24F_z%24.%20Differences%20between%20those%20channels%20generate%20%24M_x%24%20and%20%24M_y%24%3B%20horizontal%20forces%20also%20contribute%20when%20the%20measurement%20origin%20is%20below%20the%20surface.%20At%20the%20surface%2C%20the%20uncorrected%20COP%20is%20%24x%3D-M_y%2FF_z%24%2C%20%24y%3DM_x%2FF_z%24.%0A%0A%20%20%20%20The%20returned%20%60grf%60%20columns%20are%20**%60Fx%2C%20Fy%2C%20Fz%2C%20Mx%2C%20My%2C%20Tz%60**%3A%20the%20last%20column%20is%20the%20**free%20moment%20at%20the%20COP**%2C%20%24T_z%3DM_z-F_y%20x%2BF_x%20y%24.%20The%20historical%20code%20calls%20this%20column%20%60Mz%60%2C%20but%20it%20is%20not%20the%20original%20moment%20about%20the%20plate%20origin.%20Forces%20are%20in%20N%2C%20moments%20in%20N%20m%2C%20and%20COP%20in%20m.%20With%20negligible%20%24F_z%24%2C%20COP%20and%20free%20moment%20inferred%20through%20COP%20are%20not%20reliable.%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%20The%20legacy%20implementation's%20COP%20polynomial%20evaluation%20has%20been%20corrected%3A%20the%20manufacturer's%20coefficients%20use%20**millimetres**%2C%20and%20both%20corrections%20use%20the%20original%20measured%20%24(x%2Cy)%24.%20The%20public%20result%20is%20converted%20back%20to%20metres.%20Applying%20those%20coefficients%20directly%20to%20metres%2C%20or%20feeding%20corrected%20%24x%24%20into%20the%20%24y%24%20correction%2C%20changes%20the%20result.%20The%20correction%20is%20model-%20and%20mounting-specific%3B%20see%20section%208.4.3%20of%20the%20%5BKistler%20manual%5D(https%3A%2F%2Fassets.kistler.com.cn%2FSAPCommerce_Download_original%2F002-462e.pdf).%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%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20%23%20'%25matplotlib%20inline'%20command%20supported%20automatically%20in%20marimo%0A%20%20%20%20return%20(np%2C)%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20repo_file)%3A%0A%20%20%20%20%23%20load%20data%20file%0A%20%20%20%20data%20%3D%20np.loadtxt(repo_file('data%2Fkistler_fp_data.txt')%2C%20delimiter%3D'%5Ct'%2C%20skiprows%3D1)%0A%20%20%20%20data.shape%0A%20%20%20%20return%20(data%2C)%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20%22%22%22Kistler%20force%20plate%20calibration.%22%22%22%0A%0A%0A%20%20%20%20__author__%20%3D%20'Marcos%20Duarte%2C%20https%3A%2F%2Fgithub.com%2Fdemotu%2FBMC'%0A%20%20%20%20__version__%20%3D%20'kistler_fp_cal.py%20v.1%202014%2F12%2F12'%0A%0A%0A%20%20%20%20def%20kistler_fp_cal(data%2C%20S_matrix%3DNone%2C%20fxfy_range%3D0%2C%20fz_range%3D0%2C%20origin%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fp_type%3D3%2C%20show%3DFalse%2C%20axs%3DNone)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Kistler%20force%20plate%20calibration%0A%0A%20%20%20%20%20%20%20%20In%20order%20to%20get%20proper%20signals%20of%20a%20Kistler%20force%20plate%2C%20we%20have%20to%0A%20%20%20%20%20%20%20%20calibrate%20the%20acquired%20data%20according%20to%20the%20factory%20calibration%20(i.e.%2C%0A%20%20%20%20%20%20%20%20transform%20the%20readed%20values%20in%20volts%20of%20the%208%20channels%20to%20values%20in%20newtons%0A%20%20%20%20%20%20%20%20for%20fx12%2C%20fx34%2C%20fy14%2C%20fy23%2C%20fz1%2C%20fz2%2C%20fz3%2C%20fz4)%20and%20then%20calculate%20the%0A%20%20%20%20%20%20%20%20resultant%20forces%20(Fx%2C%20Fy%2C%20Fz)%2C%20resultant%20moments%20of%20force%20(Mx%2C%20My%2C%20Mz)%2C%0A%20%20%20%20%20%20%20%20and%20center%20of%20pressure%20(COPx%2C%20COPy)%20quantities.%20See%20%5B1%5D_%20and%20%5B2%5D_%0A%0A%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20----------%0A%20%20%20%20%20%20%20%20data%20%20%3A%20array_like%20%5Bfx12%2C%20fx34%2C%20fy14%2C%20fy23%2C%20fz1%2C%20fz2%2C%20fz3%2C%20fz4%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20Kistler%20force%20plate%20data%20(8%20columns%2C%20in%20Volts)%0A%20%20%20%20%20%20%20%20S_matrix%20%20%3A%20array_like%0A%20%20%20%20%20%20%20%20%20%20%20%20sensitivity%20matrix%20for%20Kistler%20force%20plate%20(8%20columns)%20and%20at%20least%0A%20%20%20%20%20%20%20%20%20%20%20%20one%20row%0A%20%20%20%20%20%20%20%20fxfy_range%20%20%3A%20number%20%5B0%2C%201%2C%202%2C%203%5D%2C%20optional%0A%20%20%20%20%20%20%20%20%20%20%20%20Fx%2FFy%20amplifier%20range%20used%20in%20the%20data%20acquisition%0A%20%20%20%20%20%20%20%20%20%20%20%20Fx%2FFy%20%5BkN%5D%3A%200.25%2C%201.25%2C%202.5%2C%205%0A%20%20%20%20%20%20%20%20%20%20%20%20This%20is%20only%20used%20if%20the%20sensitivity%20matrix%20has%20more%20than%20one%20row%0A%20%20%20%20%20%20%20%20%20%20%20%20and%20the%20first%20four%20columns%20of%20the%20corresponding%20row%20are%20selected.%0A%20%20%20%20%20%20%20%20fz_range%20%20%3A%20number%20%5B0%2C%201%2C%202%2C%203%5D%2C%20optional%0A%20%20%20%20%20%20%20%20%20%20%20%20Fz%20amplifier%20range%20used%20in%20the%20data%20acquisition%0A%20%20%20%20%20%20%20%20%20%20%20%20Fz%20%5BkN%5D%3A%201%2C%205%2C%2010%2C%2020%0A%20%20%20%20%20%20%20%20%20%20%20%20This%20is%20only%20used%20if%20the%20sensitivity%20matrix%20has%20more%20than%20one%20row%0A%20%20%20%20%20%20%20%20%20%20%20%20and%20the%20last%20four%20columns%20of%20the%20corresponding%20row%20are%20selected.%0A%20%20%20%20%20%20%20%20origin%20%20%3A%20array_like%20%5Ba%2C%20b%2C%20az0%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20coordinates%20of%20the%20force%20plate%20origin%20(az0%20is%20negative%2C%20in%20meters)%0A%20%20%20%20%20%20%20%20fp_type%20%20%3A%20number%20%5B0%2C%201%2C%202%2C%203%2C%204%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20type%20of%20force%20plate%20to%20be%20used%20in%20the%20COP%20correction%0A%20%20%20%20%20%20%20%20%20%20%20%200%3A%20no%20COP%20correction%0A%20%20%20%20%20%20%20%20%20%20%20%201%3A%20type%209281E11%0A%20%20%20%20%20%20%20%20%20%20%20%202%3A%20type%209281E%20and%209281EA%20(SN%3A%20%3C%3D%20616901)%0A%20%20%20%20%20%20%20%20%20%20%20%203%3A%20type%209281E%20and%209281EA%20(SN%3A%20%3E%3D%20616902)%0A%20%20%20%20%20%20%20%20%20%20%20%204%3A%20type%209287C%2C%209287CA%0A%20%20%20%20%20%20%20%20show%20%20%3A%20bool%2C%20optional%20(default%20%3D%20False)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20True%20(1)%2C%20plot%20data%20in%20matplotlib%20figure.%0A%20%20%20%20%20%20%20%20axs%20%20%3A%20a%20matplotlib.axes.Axes%20instance%2C%20optional%20(default%20%3D%20None).%0A%0A%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20-------%0A%20%20%20%20%20%20%20%20grf%20%20%20%20%3A%20numpy%20array%20%5BFx%2C%20Fy%2C%20Fz%2C%20Mx%2C%20My%2C%20Tz%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Forces%20in%20N%2C%20surface-origin%20Mx%2FMy%20and%20free%20moment%20Tz%20in%20Nm.%0A%20%20%20%20%20%20%20%20cop%20%20%20%20%3A%20numpy%20array%20%5BCOPx%2C%20COPy%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20center%20of%20pressure%20data%0A%0A%20%20%20%20%20%20%20%20References%0A%20%20%20%20%20%20%20%20----------%0A%20%20%20%20%20%20%20%20..%20%5B1%5D%20http%3A%2F%2Fisbweb.org%2Fsoftware%2Fmovanal%2Fvaughan%2Fkistler.pdf%0A%20%20%20%20%20%20%20%20..%20%5B2%5D%20kistler_force_plate_calculation.py%0A%0A%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20if%20S_matrix%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20sensitivity%20matrix%20for%20Kistler%20force%20plate%209281EA%20Serial%20no.%204402018%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20calibrated%20range%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fx%2FFy%20%5BkN%5D%3A%200.25%2C%201.25%2C%202.5%2C%205%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Fz%20%5BkN%5D%3A%20%20%20%201%2C%205%2C%2010%2C%2020%0A%20%20%20%20%20%20%20%20%20%20%20%20S_matrix%20%3D%20np.array(%5B%5B38.117%2C%2037.723%2C%2038.062%2C%2038.008%2C%2019.492%2C%2019.445%2C%2019.426%2C%2019.457%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%207.623%2C%20%207.545%2C%20%207.212%2C%20%207.602%2C%20%203.898%2C%20%203.889%2C%20%203.885%2C%20%203.891%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%203.803%2C%20%203.761%2C%20%203.800%2C%20%203.796%2C%20%201.951%2C%20%201.945%2C%20%201.944%2C%20%201.948%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%201.901%2C%20%201.881%2C%20%201.900%2C%20%201.898%2C%20%200.976%2C%20%200.973%2C%20%200.972%2C%20%200.974%5D%5D)%0A%20%20%20%20%20%20%20%20S_matrix%20%3D%20np.atleast_2d(S_matrix)%0A%20%20%20%20%20%20%20%20if%20S_matrix.shape%5B0%5D%20%3D%3D%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20S_matrix%20%3D%20S_matrix%5B0%5D%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20S_matrix%20%3D%20np.hstack((S_matrix%5Bfxfy_range%2C%200%3A4%5D%2C%20S_matrix%5Bfz_range%2C%204%3A8%5D))%0A%0A%20%20%20%20%20%20%20%20if%20origin%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20origin%20for%20Kistler%20force%20plate%209281EA%20Serial%20no.%204402018%0A%20%20%20%20%20%20%20%20%20%20%20%20origin%20%3D%20np.array(%5B0.120%2C%200.200%2C%20-0.048%5D)%0A%20%20%20%20%20%20%20%20a%2C%20b%2C%20az0%20%3D%20np.hsplit(np.asarray(origin)%2C%203)%0A%0A%20%20%20%20%20%20%20%20%23%20COP%20correction%20coefficients%0A%20%20%20%20%20%20%20%20if%20fp_type%20%3D%3D%201%3A%20%20%20%20%23%20Type%209281E11%0A%20%20%20%20%20%20%20%20%20%20%20%20Px%20%3D%20%5B2.51997E-15%2C%20-2.18826E-10%2C%20-2.69254E-07%2C%20-4.85912E-11%2C%204.55731E-6%2C%20-4.18892E-2%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20Py%20%3D%20%5B2.83750E-15%2C%20-1.00051E-10%2C%20-2.05349E-06%2C%20-1.16374E-10%2C%204.71553E-6%2C%206.89265E-2%5D%0A%20%20%20%20%20%20%20%20elif%20fp_type%20%3D%3D%202%3A%20%20%23%20Type%209281E%20and%209281EA%20(SN%3A%20%3C%3D%20616901)%0A%20%20%20%20%20%20%20%20%20%20%20%20Px%20%3D%20%5B1.1604E-14%2C%20-8.39091E-10%2C%20-1.44293E-6%2C%20-2.85927E-10%2C%202.05575E-5%2C%20-0.113525%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20Py%20%3D%20%5B1.27251E-14%2C%20-3.13238E-10%2C%20-3.33888E-6%2C%20-6.49641E-10%2C%201.53937E-5%2C%201.12624E-1%5D%0A%20%20%20%20%20%20%20%20elif%20fp_type%20%3D%3D%203%3A%20%20%23%20Type%209281E%20and%209281EA%20(SN%3A%20%3E%3D%20616902)%0A%20%20%20%20%20%20%20%20%20%20%20%20Px%20%3D%20%5B7.92063E-15%2C%20-5.821E-10%2C%20-2.77102E-6%2C%20-1.76083E-10%2C%201.29695E-5%2C%20-0.0413979%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20Py%20%3D%20%5B8.82869E-15%2C%20-2.48554E-10%2C%20-1.76282E-6%2C%20-4.22186E-10%2C%201.2091E-5%2C%205.16279E-2%5D%0A%20%20%20%20%20%20%20%20elif%20fp_type%20%3D%3D%204%3A%20%20%23%20Type%209287C%2C%209287CA%0A%20%20%20%20%20%20%20%20%20%20%20%20Px%20%3D%20%5B1.72454E-16%2C%20-4.82275E-11%2C%203.30016E-7%2C%20-9.46569E-12%2C%202.78736E-6%2C%20-8.20399E-3%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20Py%20%3D%20%5B2.20428E-16%2C%20-1.80864E-11%2C%20-7.30249E-7%2C%20-3.03080E-11%2C%202.64974E-6%2C%205.41166E-2%5D%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20Px%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20Py%20%3D%20%5B%5D%0A%0A%20%20%20%20%20%20%20%20%23%20Calibration%0A%20%20%20%20%20%20%20%20data%20%3D%201000*data%2FS_matrix%0A%0A%20%20%20%20%20%20%20%20fx12%2C%20fx34%2C%20fy14%2C%20fy23%2C%20fz1%2C%20fz2%2C%20fz3%2C%20fz4%20%3D%20np.hsplit(data%2C%208)%0A%0A%20%20%20%20%20%20%20%20%23%20Medio-lateral%20force%0A%20%20%20%20%20%20%20%20Fx%20%3D%20fx12%20%2B%20fx34%0A%20%20%20%20%20%20%20%20%23%20Anterior-posterior%20force%0A%20%20%20%20%20%20%20%20Fy%20%3D%20fy14%20%2B%20fy23%0A%20%20%20%20%20%20%20%20%23%20Vertical%20force%0A%20%20%20%20%20%20%20%20Fz%20%3D%20fz1%20%2B%20fz2%20%2B%20fz3%20%2B%20fz4%0A%20%20%20%20%20%20%20%20%23%20Plate%20moment%20about%20X-axis%0A%20%20%20%20%20%20%20%20Mx%20%3D%20b%20*%20(fz1%20%2B%20fz2%20-%20fz3%20-%20fz4)%0A%20%20%20%20%20%20%20%20%23%20Plate%20moment%20about%20Y-axis%0A%20%20%20%20%20%20%20%20My%20%3D%20a%20*%20(-fz1%20%2B%20fz2%20%2B%20fz3%20-%20fz4)%0A%20%20%20%20%20%20%20%20%23%20Plate%20moment%20about%20Z-axis%0A%20%20%20%20%20%20%20%20Mz%20%3D%20b%20*%20(-fx12%20%2B%20fx34)%20%2B%20a%20*%20(fy14%20-%20fy23)%0A%20%20%20%20%20%20%20%20%23%20Plate%20moment%20about%20top%20plate%20surface%0A%20%20%20%20%20%20%20%20Mx%20%3D%20Mx%20%2B%20Fy*az0%0A%20%20%20%20%20%20%20%20%23%20Plate%20moment%20about%20top%20plate%20surface%0A%20%20%20%20%20%20%20%20My%20%3D%20My%20-%20Fx*az0%0A%20%20%20%20%20%20%20%20%23%20X-Coordinate%20of%20force%20application%20point%20(COP)%0A%20%20%20%20%20%20%20%20ax%20%3D%20-My%20%2F%20Fz%0A%20%20%20%20%20%20%20%20%23%20Y-Coordinate%20of%20force%20application%20point%20(COP)%0A%20%20%20%20%20%20%20%20ay%20%3D%20Mx%20%2F%20Fz%0A%20%20%20%20%20%20%20%20%23%20Coefficient%20of%20Friction%20x-component%0A%20%20%20%20%20%20%20%20%23COFx%20%3D%20Fx%20%2F%20Fz%0A%20%20%20%20%20%20%20%20%23%20Coefficient%20of%20Friction%20y-component%0A%20%20%20%20%20%20%20%20%23COFy%20%3D%20Fy%20%2F%20Fz%0A%20%20%20%20%20%20%20%20%23%20The%20manufacturer's%20polynomial%20table%20uses%20measured%20COP%20in%20millimetres.%0A%20%20%20%20%20%20%20%20%23%20Evaluate%20both%20corrections%20from%20the%20original%20coordinates%2C%20then%20return%20metres.%0A%20%20%20%20%20%20%20%20%23%20Kistler%209287C_002-462e-03.11%2C%20section%208.4.3.%0A%20%20%20%20%20%20%20%20axm%2C%20aym%20%3D%201000%20*%20ax%2C%201000%20*%20ay%0A%20%20%20%20%20%20%20%20if%20Px%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20Dax%20%3D%20(Px%5B0%5D*aym**4%20%2B%20Px%5B1%5D*aym**2%20%2B%20Px%5B2%5D)*axm**3%20%2B%20(Px%5B3%5D*aym**4%20%2B%20Px%5B4%5D*aym**2%20%2B%20Px%5B5%5D)*axm%0A%20%20%20%20%20%20%20%20%20%20%20%20ax%20%3D%20ax%20-%20Dax%20%2F%201000%0A%20%20%20%20%20%20%20%20if%20Py%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20Day%20%3D%20(Py%5B0%5D*axm**4%20%2B%20Py%5B1%5D*axm**2%20%2B%20Py%5B2%5D)*aym**3%20%2B%20(Py%5B3%5D*axm**4%20%2B%20Py%5B4%5D*axm**2%20%2B%20Py%5B5%5D)*aym%0A%20%20%20%20%20%20%20%20%20%20%20%20ay%20%3D%20ay%20-%20Day%20%2F%201000%0A%20%20%20%20%20%20%20%20%23%20Free%20moment%0A%20%20%20%20%20%20%20%20Mz%20%3D%20Mz%20-%20Fy*ax%20%2B%20Fx*ay%0A%0A%20%20%20%20%20%20%20%20grf%20%3D%20np.hstack((Fx%2C%20Fy%2C%20Fz%2C%20Mx%2C%20My%2C%20Mz))%0A%20%20%20%20%20%20%20%20cop%20%3D%20np.hstack((ax%2C%20ay))%0A%0A%20%20%20%20%20%20%20%20if%20show%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20plot_kistler(grf%2C%20cop%2C%20axs)%0A%0A%20%20%20%20%20%20%20%20return%20grf%2C%20cop%0A%0A%0A%20%20%20%20def%20plot_kistler(grf%2C%20cop%2C%20axs)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Plot%20results%20of%20the%20detect_peaks%20function%2C%20see%20its%20help.%22%22%22%0A%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20%20%20%20%20except%20ImportError%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print('matplotlib%20is%20not%20available.')%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20grf%20%3D%20np.hstack((grf%2C%20cop))%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20axs%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_%2C%20axs%20%3D%20plt.subplots(4%2C%202%2C%20figsize%3D(8%2C%206)%2C%20sharex%3DTrue)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%20%3D%20axs.flatten()%0A%20%20%20%20%20%20%20%20%20%20%20%20ylabel%20%3D%20%5B'Fx%20%5BN%5D'%2C%20'Fy%20%5BN%5D'%2C%20'Fz%20%5BN%5D'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'Mx%20%5BNm%5D'%2C%20'My%20%5BNm%5D'%2C%20'Mz%20%5BNm%5D'%2C%20'COPx%20%5Bm%5D'%2C%20'COPy%20%5Bm%5D'%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20i%2C%20axi%20in%20enumerate(axs)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axi.plot(grf%5B%3A%2C%20i%5D%2C%20'b'%2C%20lw%3D1)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axi.set_ylabel(ylabel%5Bi%5D%2C%20fontsize%3D14)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axi.yaxis.set_major_locator(plt.MaxNLocator(4))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axi.yaxis.set_label_coords(-.2%2C%200.5)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B6%5D.set_xlabel('Sample%20%23'%2C%20fontsize%3D14)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B7%5D.set_xlabel('Sample%20%23'%2C%20fontsize%3D14)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.suptitle('Ground%20reaction%20force%20data'%2C%20y%3D1.02%2C%20fontsize%3D16)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.tight_layout(h_pad%3D.1)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20plt.grid()%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.show()%0A%0A%20%20%20%20return%20(kistler_fp_cal%2C)%0A%0A%0A%40app.cell%0Adef%20_(data%2C%20kistler_fp_cal)%3A%0A%20%20%20%20grf%2C%20cop%20%3D%20kistler_fp_cal(data%5B%3A%2C%201%3A%5D%2C%20fxfy_range%3D0%2C%20fz_range%3D1%2C%20show%3DTrue)%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%20%E2%80%94%20resultant%20and%20pressure%20point.**%20With%20four%20equal%20vertical%20sensor%20forces%20of%20100%20N%2C%20zero%20horizontal%20forces%20and%20a%20symmetric%20plate%2C%20predict%20%24F_z%24%20and%20COP.%20Then%20use%20surface%20moments%20%24M_x%3D10%24%20N%20m%2C%20%24M_y%3D-20%24%20N%20m%20with%20%24F_z%3D500%24%20N%20to%20find%20the%20uncorrected%20COP.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Worked%20solution%20%E2%80%94%20Exercise%202%20%E2%80%94%20resultant%20and%20pressure%20point%0A%0A%20%20%20%20The%20equal%20forces%20give%20%24F_z%3D400%24%20N%20and%20zero%20moment%20differences%2C%20so%20COP%20is%20at%20the%20origin.%20In%20the%20second%20case%2C%20%24x%3D-(-20)%2F500%3D0.040%24%20m%20and%20%24y%3D10%2F500%3D0.020%24%20m.%20A%20plate-specific%20polynomial%20correction%20is%20a%20further%20calibration%20step%2C%20separate%20from%20these%20balance%20equations.%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%20Function%20kistler_fp_cal.py%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(kistler_fp_cal%2C%20mo)%3A%0A%20%20%20%20import%20inspect%0A%20%20%20%20mo.ui.code_editor(inspect.getsource(kistler_fp_cal)%2C%20language%3D%22python%22%2C%20disabled%3DTrue)%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**Exercise%203%20%E2%80%94%20low-force%20sensitivity.**%20A%201%20N%20m%20uncertainty%20affects%20%24M_y%24.%20Compare%20its%20contribution%20to%20COP%20uncertainty%20at%20%24F_z%3D500%24%20N%20and%205%20N%2C%20holding%20%24F_z%24%20fixed.%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%20From%20%24x%3D-M_y%2FF_z%24%2C%20the%20uncertainty%20magnitude%20is%20%241%2F%7CF_z%7C%24%3A%200.002%20m%20versus%200.2%20m.%20The%20same%20moment%20error%20causes%20a%20hundredfold%20larger%20COP%20error%20near%20unloading.%20Choose%20a%20contact%20threshold%20from%20acquisition%20noise%20and%20analysis%20needs%3B%20a%20universal%20threshold%20is%20not%20established%20by%20this%20demonstration.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%20Checkpoint%20questions%0A%0A%20%20%20%20-%20Which%20quantities%20must%20match%20the%20plate%20serial%20number%20and%20acquisition%20settings%3F%0A%20%20%20%20-%20Why%20does%20the%20surface-origin%20offset%20affect%20moments%20when%20shear%20force%20is%20present%3F%0A%20%20%20%20-%20How%20could%20a%20plausible%20COP%20plot%20conceal%20a%20sign%20or%20unit%20error%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Checkpoint%20answers%0A%0A%20%20%20%20Use%20the%20actual%20sensitivities%2C%20amplifier%20ranges%2C%20geometry%2C%20channel%20convention%20and%20applicable%20correction.%20Moving%20the%20origin%20changes%20moment%20by%20a%20position%20cross%20force%20term.%20Validate%20signs%20with%20known%20loading%20locations%2C%20check%20metres%20versus%20millimetres%2C%20and%20compare%20a%20known%20static%20load%3B%20smoothness%20alone%20is%20insufficient.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%20Problems%0A%0A%20%20%20%201.%20Four%20vertical%20channels%20each%20record%200.050%20V%20with%20sensitivity%202%20mV%2FN.%20Horizontal%20channels%20are%20zero.%20Find%20the%20total%20vertical%20force%20and%20uncorrected%20COP%20on%20a%20symmetric%20plate.%0A%20%20%20%202.%20At%20the%20plate%20surface%2C%20%24F%3D(20%2C30%2C600)%24%20N%2C%20%24M_x%3D12%24%20N%20m%2C%20%24M_y%3D-24%24%20N%20m%20and%20origin%20moment%20%24M_z%3D3%24%20N%20m.%20Find%20the%20uncorrected%20COP%20and%20free%20moment.%0A%20%20%20%203.%20If%20%24F_z%3D0%24%2C%20should%20the%20COP%20be%20reported%20as%20the%20origin%2C%20infinity%2C%20or%20undefined%3F%0A%20%20%20%204.%20A%20sensitivity%20of%204%20mV%2FN%20is%20mistakenly%20replaced%20by%202%20mV%2FN.%20What%20happens%20to%20the%20inferred%20force%20from%20that%20channel%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Final%20answers%20to%20the%20problems%0A%0A%20%20%20%201.%20100%20N%3B%20COP%20%24(0%2C0)%24%20m.%0A%20%20%20%202.%20COP%20%24(0.040%2C0.020)%24%20m%3B%20%24T_z%3D2.2%24%20N%20m.%0A%20%20%20%203.%20Undefined.%0A%20%20%20%204.%20The%20inferred%20force%20doubles.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%20Go%20deeper%0A%0A%20%20%20%20Use%20a%20known%20load%20at%20several%20positions%20to%20check%20force%20balance%2C%20COP%20signs%20and%20free%20moment.%20Review%20the%20sensitivity%20table%20for%20your%20serial%20number%20and%20distinguish%20factory%20calibration%20from%20an%20in-situ%20re-calibration.%20The%20companion%20%5Bforce-plate%20calibration%20guide%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fforce_plate_calibration.py)%20develops%20the%20latter.%0A%0A%20%20%20%20%23%23%23%20Video%20lectures%20on%20the%20Internet%0A%0A%20%20%20%20-%20%5BMIT%208.01SC%20Classical%20Mechanics%5D(https%3A%2F%2Focw.mit.edu%2Fcourses%2F8-01sc-classical-mechanics-fall-2016%2F)%20%E2%80%94%20review%20torque%20and%20equilibrium%2C%20then%20explain%20why%20the%20COP%20moment%20equations%20divide%20by%20vertical%20force.%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-%20%5BKistler%20Force%20Plate%20Formulae%5D(https%3A%2F%2Fisbweb.org%2Fsoftware%2Fmovanal%2Fvaughan%2Fkistler.pdf)%0A%0A%20%20%20%20-%20%5BQualisys%20Kistler%20force-plate%20settings%5D(https%3A%2F%2Fdocs.qualisys.com%2Fqtm%2Fcontent%2Fproject_options%2Fforce_plate_settings_kistler.htm)%20%E2%80%94%20primary%20integration%20documentation%20on%20calibration%2C%20ranges%20and%20geometry.%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
e2b46a835e71cf821e5bc164bcb85dee