%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%22marimo%3E%3D0.23.9%22%2C%20%22numpy%3E%3D2.0%22%2C%20%22matplotlib%3E%3D3.9%22%2C%20%22sympy%3E%3D1.13%22%5D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.25.2%22%0Aapp%20%3D%20marimo.App()%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%20Ellipsoids%2C%20rotation%20sequences%20and%20a%20marker-derived%20basis%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%0A%20%20%20%20%23%23%20How%20to%20use%20this%20guide%0A%0A%20%20%20%20An%20ellipsoid%20makes%20orientation%20visible%3A%20unlike%20a%20sphere%2C%20its%20unequal%20axes%20let%20us%20see%20a%20rotation.%20Predict%20the%20long-axis%20direction%20before%20running%20each%20plot%2C%20then%20compare%20a%20rotated%20point%20with%20the%20rotated%20surface.%20The%20Exercises%20have%20collapsed%20worked%20solutions%3B%20the%20independent%20Problems%20provide%20final%20answers%20only.%0A%0A%20%20%20%20**Opening%20challenge.**%20The%20surface%20is%20%24x%5E2%2B3y%5E2%2B15z%5E2%3D1%24.%20Which%20axis%20is%20longest%3F%20If%20it%20is%20rotated%20about%20%24x%24%2C%20does%20that%20longest%20axis%20move%3F%0A%0A%20%20%20%20%23%23%20Python%20setup%0A%0A%20%20%20%20NumPy%20builds%20the%20surface%20mesh%20and%20Matplotlib%20renders%20it.%20SymPy%20also%20shows%20rotation%20products%20algebraically.%20No%20external%20files%20are%20needed.%20You%20need%20matrix%20multiplication%2C%20sines%20and%20cosines.%0A%0A%20%20%20%20%23%23%20From%20the%20equation%20to%20a%20surface%0A%0A%20%20%20%20Write%20the%20ellipsoid%20as%20%24(x%2Fa)%5E2%2B(y%2Fb)%5E2%2B(z%2Fc)%5E2%3D1%24.%20Its%20semiaxes%20are%20%24a%3D1%24%2C%20%24b%3D1%2F%5Csqrt3%24%20and%20%24c%3D1%2F%5Csqrt%7B15%7D%24.%20The%20sampled%20angles%20describe%20surface%20points%2C%20not%20the%20orientation%20angles%20of%20the%20whole%20body.%20A%20rotation%20acts%20on%20the%20stacked%20Cartesian%20coordinates.%0A%0A%20%20%20%20**Exercise%201.**%20Find%20the%20three%20positive%20axis%20intercepts%20and%20check%20one%20in%20the%20original%20equation.%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%20intercepts%20are%20%24(1%2C0%2C0)%24%2C%20%24(0%2C1%2F%5Csqrt3%2C0)%24%20and%20%24(0%2C0%2C1%2F%5Csqrt%7B15%7D)%24.%20For%20the%20second%2C%20%243(1%2F%5Csqrt3)%5E2%3D1%24.%20The%20%24x%24%20semiaxis%20is%20longest%2C%20and%20rotation%20about%20%24x%24%20leaves%20it%20fixed.%0A%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20sympy%20as%20sym%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20return%20np%2C%20sym%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20rotationGlobalX(alpha)%3A%0A%20%20%20%20%20%20%20%20return%20np.array(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20np.cos(alpha)%2C%20-np.sin(alpha)%5D%2C%20%5B0%2C%20np.sin(alpha)%2C%20np.cos(alpha)%5D%5D)%0A%0A%20%20%20%20def%20rotationGlobalY(beta)%3A%0A%20%20%20%20%20%20%20%20return%20np.array(%5B%5Bnp.cos(beta)%2C%200%2C%20np.sin(beta)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B-np.sin(beta)%2C%200%2C%20np.cos(beta)%5D%5D)%0A%0A%20%20%20%20def%20rotationGlobalZ(gamma)%3A%0A%20%20%20%20%20%20%20%20return%20np.array(%5B%5Bnp.cos(gamma)%2C%20-np.sin(gamma)%2C%200%5D%2C%20%5Bnp.sin(gamma)%2C%20np.cos(gamma)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%0A%20%20%20%20def%20rotationLocalX(alpha)%3A%0A%20%20%20%20%20%20%20%20return%20np.array(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20np.cos(alpha)%2C%20np.sin(alpha)%5D%2C%20%5B0%2C%20-np.sin(alpha)%2C%20np.cos(alpha)%5D%5D)%0A%0A%20%20%20%20def%20rotationLocalY(beta)%3A%0A%20%20%20%20%20%20%20%20return%20np.array(%5B%5Bnp.cos(beta)%2C%200%2C%20-np.sin(beta)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5Bnp.sin(beta)%2C%200%2C%20np.cos(beta)%5D%5D)%0A%0A%20%20%20%20def%20rotationLocalZ(gamma)%3A%0A%20%20%20%20%20%20%20%20return%20np.array(%5B%5Bnp.cos(gamma)%2C%20np.sin(gamma)%2C%200%5D%2C%20%5B-np.sin(gamma)%2C%20np.cos(gamma)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20rotationGlobalX%2C%0A%20%20%20%20%20%20%20%20rotationGlobalY%2C%0A%20%20%20%20%20%20%20%20rotationGlobalZ%2C%0A%20%20%20%20%20%20%20%20rotationLocalX%2C%0A%20%20%20%20%20%20%20%20rotationLocalY%2C%0A%20%20%20%20%20%20%20%20rotationLocalZ%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20np%2C%0A%20%20%20%20rotationGlobalX%2C%0A%20%20%20%20rotationGlobalY%2C%0A%20%20%20%20rotationGlobalZ%2C%0A%20%20%20%20rotationLocalX%2C%0A%20%20%20%20rotationLocalY%2C%0A%20%20%20%20rotationLocalZ%2C%0A)%3A%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20plt.rcParams%5B'figure.figsize'%5D%20%3D%20(10%2C%2010)%0A%20%20%20%20_coefs%20%3D%20(1%2C%203%2C%2015)%0A%20%20%20%20(_rx%2C%20_ry%2C%20_rz)%20%3D%201%20%2F%20np.sqrt(_coefs)%0A%20%20%20%20_u%20%3D%20np.linspace(0%2C%202%20*%20np.pi%2C%2030)%0A%20%20%20%20_v%20%3D%20np.linspace(0%2C%20np.pi%2C%2030)%0A%20%20%20%20_x%20%3D%20_rx%20*%20np.outer(np.cos(_u)%2C%20np.sin(_v))%0A%20%20%20%20_y%20%3D%20_ry%20*%20np.outer(np.sin(_u)%2C%20np.sin(_v))%0A%20%20%20%20_z%20%3D%20_rz%20*%20np.outer(np.ones_like(_u)%2C%20np.cos(_v))%0A%20%20%20%20_fig%20%3D%20plt.figure(figsize%3Dplt.figaspect(1))%0A%20%20%20%20_ax%20%3D%20_fig.add_subplot(111%2C%20projection%3D'3d')%0A%20%20%20%20_ax.set_box_aspect((1%2C%201%2C%201))%0A%20%20%20%20_xr%20%3D%20np.reshape(_x%2C%20(1%2C%20-1))%0A%20%20%20%20_yr%20%3D%20np.reshape(_y%2C%20(1%2C%20-1))%0A%20%20%20%20_zr%20%3D%20np.reshape(_z%2C%20(1%2C%20-1))%0A%20%20%20%20RX%20%3D%20rotationGlobalX(np.pi%20%2F%203)%0A%20%20%20%20RY%20%3D%20rotationGlobalY(np.pi%20%2F%203)%0A%20%20%20%20RZ%20%3D%20rotationGlobalZ(np.pi%20%2F%203)%0A%20%20%20%20_Rx%20%3D%20rotationLocalX(np.pi%20%2F%203)%0A%20%20%20%20_Ry%20%3D%20rotationLocalY(np.pi%20%2F%203)%0A%20%20%20%20_Rz%20%3D%20rotationLocalZ(np.pi%20%2F%203)%0A%20%20%20%20_rRotx%20%3D%20RZ%20%40%20RY%20%40%20RX%20%40%20np.vstack((_xr%2C%20_yr%2C%20_zr))%0A%20%20%20%20print(np.shape(_rRotx))%0A%20%20%20%20_ax.plot_surface(np.reshape(_rRotx%5B0%2C%20%3A%5D%2C%20(30%2C%2030))%2C%20np.reshape(_rRotx%5B1%2C%20%3A%5D%2C%20(30%2C%2030))%2C%20np.reshape(_rRotx%5B2%2C%20%3A%5D%2C%20(30%2C%2030))%2C%20rstride%3D4%2C%20cstride%3D4%2C%20color%3D'b')%0A%20%20%20%20_max_radius%20%3D%20max(_rx%2C%20_ry%2C%20_rz)%0A%20%20%20%20for%20_axis%20in%20'xyz'%3A%0A%20%20%20%20%20%20%20%20getattr(_ax%2C%20'set_%7B%7Dlim'.format(_axis))((-_max_radius%2C%20_max_radius))%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20(plt%2C)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20np%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20rotationGlobalX%2C%0A%20%20%20%20rotationGlobalY%2C%0A%20%20%20%20rotationGlobalZ%2C%0A%20%20%20%20rotationLocalX%2C%0A%20%20%20%20rotationLocalY%2C%0A%20%20%20%20rotationLocalZ%2C%0A)%3A%0A%20%20%20%20_coefs%20%3D%20(1%2C%203%2C%2015)%0A%20%20%20%20(_rx%2C%20_ry%2C%20_rz)%20%3D%201%20%2F%20np.sqrt(_coefs)%0A%20%20%20%20_u%20%3D%20np.linspace(0%2C%202%20*%20np.pi%2C%2030)%0A%20%20%20%20_v%20%3D%20np.linspace(0%2C%20np.pi%2C%2030)%0A%20%20%20%20_x%20%3D%20_rx%20*%20np.outer(np.cos(_u)%2C%20np.sin(_v))%0A%20%20%20%20_y%20%3D%20_ry%20*%20np.outer(np.sin(_u)%2C%20np.sin(_v))%0A%20%20%20%20_z%20%3D%20_rz%20*%20np.outer(np.ones_like(_u)%2C%20np.cos(_v))%0A%20%20%20%20_fig%20%3D%20plt.figure(figsize%3Dplt.figaspect(1))%0A%20%20%20%20_ax%20%3D%20_fig.add_subplot(111%2C%20projection%3D'3d')%0A%20%20%20%20_ax.set_box_aspect((1%2C%201%2C%201))%0A%20%20%20%20_xr%20%3D%20np.reshape(_x%2C%20(1%2C%20-1))%0A%20%20%20%20_yr%20%3D%20np.reshape(_y%2C%20(1%2C%20-1))%0A%20%20%20%20_zr%20%3D%20np.reshape(_z%2C%20(1%2C%20-1))%0A%20%20%20%20RX_1%20%3D%20rotationGlobalX(np.pi%20%2F%203)%0A%20%20%20%20RY_1%20%3D%20rotationGlobalY(np.pi%20%2F%203)%0A%20%20%20%20RZ_1%20%3D%20rotationGlobalZ(np.pi%20%2F%203)%0A%20%20%20%20_Rx%20%3D%20rotationLocalX(np.pi%20%2F%203)%0A%20%20%20%20_Ry%20%3D%20rotationLocalY(np.pi%20%2F%203)%0A%20%20%20%20_Rz%20%3D%20rotationLocalZ(np.pi%20%2F%203)%0A%20%20%20%20_rRotx%20%3D%20RY_1%20%40%20RX_1%20%40%20np.vstack((_xr%2C%20_yr%2C%20_zr))%0A%20%20%20%20print(np.shape(_rRotx))%0A%20%20%20%20_ax.plot_surface(np.reshape(_rRotx%5B0%2C%20%3A%5D%2C%20(30%2C%2030))%2C%20np.reshape(_rRotx%5B1%2C%20%3A%5D%2C%20(30%2C%2030))%2C%20np.reshape(_rRotx%5B2%2C%20%3A%5D%2C%20(30%2C%2030))%2C%20rstride%3D4%2C%20cstride%3D4%2C%20color%3D'b')%0A%20%20%20%20_max_radius%20%3D%20max(_rx%2C%20_ry%2C%20_rz)%0A%20%20%20%20for%20_axis%20in%20'xyz'%3A%0A%20%20%20%20%20%20%20%20getattr(_ax%2C%20'set_%7B%7Dlim'.format(_axis))((-_max_radius%2C%20_max_radius))%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20RX_1%2C%20RY_1%2C%20RZ_1%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20np.sin(np.arccos(0.7))%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RX_1%2C%20RY_1%2C%20RZ_1)%3A%0A%20%20%20%20print(RZ_1%20%40%20RY_1%20%40%20RX_1)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(sym)%3A%0A%20%20%20%20sym.init_printing()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(sym)%3A%0A%20%20%20%20a%2Cb%2Cg%20%3D%20sym.symbols('alpha%2C%20beta%2C%20gamma')%0A%20%20%20%20return%20a%2C%20b%2C%20g%0A%0A%0A%40app.cell%0Adef%20_(a%2C%20b%2C%20g%2C%20sym)%3A%0A%20%20%20%20RX_2%20%3D%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20sym.cos(a)%2C%20-sym.sin(a)%5D%2C%20%5B0%2C%20sym.sin(a)%2C%20sym.cos(a)%5D%5D)%0A%20%20%20%20RY_2%20%3D%20sym.Matrix(%5B%5Bsym.cos(b)%2C%200%2C%20sym.sin(b)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B-sym.sin(b)%2C%200%2C%20sym.cos(b)%5D%5D)%0A%20%20%20%20RZ_2%20%3D%20sym.Matrix(%5B%5Bsym.cos(g)%2C%20-sym.sin(g)%2C%200%5D%2C%20%5Bsym.sin(g)%2C%20sym.cos(g)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%20%20%20%20(RX_2%2C%20RY_2%2C%20RZ_2)%0A%20%20%20%20return%20RX_2%2C%20RY_2%2C%20RZ_2%0A%0A%0A%40app.cell%0Adef%20_(RX_2%2C%20RY_2%2C%20RZ_2)%3A%0A%20%20%20%20R%20%3D%20RZ_2%20%40%20RY_2%20%40%20RX_2%0A%20%20%20%20R%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20mm%20%3D%20np.array(%5B2.71%2C%2010.22%2C%2026.52%5D)%0A%20%20%20%20lm%20%3D%20np.array(%5B2.92%2C%2010.10%2C%2018.85%5D)%0A%20%20%20%20fh%20%3D%20np.array(%5B5.05%2C%2041.90%2C%2015.41%5D)%0A%20%20%20%20mc%20%3D%20np.array(%5B8.29%2C%2041.88%2C%2026.52%5D)%0A%20%20%20%20ajc%20%3D%20(mm%20%2B%20lm)%2F2%0A%20%20%20%20kjc%20%3D%20(fh%20%2B%20mc)%2F2%0A%20%20%20%20return%20ajc%2C%20kjc%2C%20lm%2C%20mm%0A%0A%0A%40app.cell%0Adef%20_(ajc%2C%20kjc%2C%20lm%2C%20mm%2C%20np)%3A%0A%20%20%20%20i%20%3D%20np.array(%5B1%2C0%2C0%5D)%0A%20%20%20%20j%20%3D%20np.array(%5B0%2C1%2C0%5D)%0A%20%20%20%20k%20%3D%20np.array(%5B0%2C0%2C1%5D)%0A%20%20%20%20v1%20%3D%20kjc%20-%20ajc%0A%20%20%20%20v1%20%3D%20v1%20%2F%20np.sqrt(v1%5B0%5D**2%2Bv1%5B1%5D**2%2Bv1%5B2%5D**2)%0A%20%20%20%20v2%20%3D%20(mm-lm)%20-%20((mm-lm)%40v1)*v1%0A%20%20%20%20v2%20%3D%20v2%2F%20np.sqrt(v2%5B0%5D**2%2Bv2%5B1%5D**2%2Bv2%5B2%5D**2)%0A%20%20%20%20v3%20%3D%20np.cross(v1%2C%20v2)%20%20%23%20preserve%20right-handedness%20for%20any%20nondegenerate%20marker%20set%0A%20%20%20%20v3%20%3D%20v3%2F%20np.sqrt(v3%5B0%5D**2%2Bv3%5B1%5D**2%2Bv3%5B2%5D**2)%0A%20%20%20%20return%20v1%2C%20v2%2C%20v3%0A%0A%0A%40app.cell%0Adef%20_(v1)%3A%0A%20%20%20%20v1%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20v1%2C%20v2%2C%20v3)%3A%0A%20%20%20%20R_1%20%3D%20np.array(%5Bv1%2C%20v2%2C%20v3%5D)%0A%20%20%20%20RGlobal%20%3D%20R_1.T%0A%20%20%20%20RGlobal%0A%20%20%20%20return%20RGlobal%2C%20R_1%0A%0A%0A%40app.cell%0Adef%20_(RGlobal%2C%20np)%3A%0A%20%20%20%20_alpha%20%3D%20np.arctan2(RGlobal%5B2%2C%201%5D%2C%20RGlobal%5B2%2C%202%5D)%20*%20180%20%2F%20np.pi%0A%20%20%20%20_alpha%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RGlobal%2C%20np)%3A%0A%20%20%20%20_beta%20%3D%20np.arctan2(-RGlobal%5B2%2C%200%5D%2C%20np.sqrt(RGlobal%5B2%2C%201%5D%20**%202%20%2B%20RGlobal%5B2%2C%202%5D%20**%202))%20*%20180%20%2F%20np.pi%0A%20%20%20%20_beta%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RGlobal%2C%20np)%3A%0A%20%20%20%20_gamma%20%3D%20np.arctan2(RGlobal%5B1%2C%200%5D%2C%20RGlobal%5B0%2C%200%5D)%20*%20180%20%2F%20np.pi%0A%20%20%20%20_gamma%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20_q%20%3D%20np.sqrt(0.5)%0A%20%20%20%20R2%20%3D%20np.array(%5B%5B0%2C%20_q%2C%20_q%5D%2C%20%5B0%2C%20_q%2C%20-_q%5D%2C%20%5B-1%2C%200%2C%200%5D%5D)%0A%20%20%20%20R2%0A%20%20%20%20return%20(R2%2C)%0A%0A%0A%40app.cell%0Adef%20_(R_1%2C%20np)%3A%0A%20%20%20%20_alpha%20%3D%20np.arctan2(R_1%5B2%2C%201%5D%2C%20R_1%5B2%2C%202%5D)%20*%20180%20%2F%20np.pi%0A%20%20%20%20_alpha%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R_1%2C%20np)%3A%0A%20%20%20%20_gamma%20%3D%20np.arctan2(R_1%5B1%2C%200%5D%2C%20R_1%5B0%2C%200%5D)%20*%20180%20%2F%20np.pi%0A%20%20%20%20_gamma%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R_1%2C%20np)%3A%0A%20%20%20%20_beta%20%3D%20np.arctan2(-R_1%5B2%2C%200%5D%2C%20np.sqrt(R_1%5B2%2C%201%5D%20**%202%20%2B%20R_1%5B2%2C%202%5D%20**%202))%20*%20180%20%2F%20np.pi%0A%20%20%20%20_beta%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RX_2%2C%20RY_2%2C%20RZ_2)%3A%0A%20%20%20%20R_2%20%3D%20RY_2%20%40%20RZ_2%20%40%20RX_2%0A%20%20%20%20R_2%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R2%2C%20np)%3A%0A%20%20%20%20_alpha%20%3D%20np.arctan2(-R2%5B1%2C%202%5D%2C%20R2%5B1%2C%201%5D)%20*%20180%20%2F%20np.pi%0A%20%20%20%20_alpha%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_gamma%20%3D%200%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20_beta%20%3D%2090%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(sym)%3A%0A%20%20%20%20sym.init_printing()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(sym)%3A%0A%20%20%20%20(a_1%2C%20b_1%2C%20g_1)%20%3D%20sym.symbols('alpha%2C%20beta%2C%20gamma')%0A%20%20%20%20return%20a_1%2C%20b_1%2C%20g_1%0A%0A%0A%40app.cell%0Adef%20_(a_1%2C%20b_1%2C%20g_1%2C%20sym)%3A%0A%20%20%20%20RX_3%20%3D%20sym.Matrix(%5B%5B1%2C%200%2C%200%5D%2C%20%5B0%2C%20sym.cos(a_1)%2C%20-sym.sin(a_1)%5D%2C%20%5B0%2C%20sym.sin(a_1)%2C%20sym.cos(a_1)%5D%5D)%0A%20%20%20%20RY_3%20%3D%20sym.Matrix(%5B%5Bsym.cos(b_1)%2C%200%2C%20sym.sin(b_1)%5D%2C%20%5B0%2C%201%2C%200%5D%2C%20%5B-sym.sin(b_1)%2C%200%2C%20sym.cos(b_1)%5D%5D)%0A%20%20%20%20RZ_3%20%3D%20sym.Matrix(%5B%5Bsym.cos(g_1)%2C%20-sym.sin(g_1)%2C%200%5D%2C%20%5Bsym.sin(g_1)%2C%20sym.cos(g_1)%2C%200%5D%2C%20%5B0%2C%200%2C%201%5D%5D)%0A%20%20%20%20(RX_3%2C%20RY_3%2C%20RZ_3)%0A%20%20%20%20return%20RX_3%2C%20RY_3%2C%20RZ_3%0A%0A%0A%40app.cell%0Adef%20_(RX_3%2C%20RY_3%2C%20RZ_3)%3A%0A%20%20%20%20RXYZ%20%3D%20RZ_3%20*%20RY_3%20*%20RX_3%0A%20%20%20%20RXYZ%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RX_3%2C%20RY_3%2C%20RZ_3)%3A%0A%20%20%20%20RZXY%20%3D%20RZ_3%20*%20RX_3%20*%20RY_3%0A%20%20%20%20RZXY%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%20Reading%20the%20sequence%20and%20the%20basis%0A%0A%20%20%20%20With%20column%20vectors%2C%20the%20rightmost%20matrix%20acts%20first%3A%20%60RZ%20%40%20RY%20%40%20RX%60%20applies%20fixed-axis%20%24x%24%2C%20then%20%24y%24%2C%20then%20%24z%24%20rotations.%20The%20functions%20named%20%60rotationLocalX%2FY%2FZ%60%20in%20the%20preserved%20example%20return%20the%20transposes%20of%20the%20corresponding%20active%20matrices%3B%20their%20names%20alone%20do%20not%20specify%20a%20moving-axis%20sequence.%0A%0A%20%20%20%20The%20marker%20example%20builds%20two%20orthogonal%20directions%20first%20and%20closes%20the%20triad%20with%20their%20cross%20product.%20This%20makes%20handedness%20explicit.%20The%20final%20gimbal-lock%20example%20now%20uses%20exact%20%241%2F%5Csqrt2%24%20entries%3A%20the%20old%20rounded%200.70%20and%200.71%20values%20were%20not%20exactly%20orthogonal.%0A%0A%20%20%20%20**Exercise%202.**%20Why%20can%20an%20inverse%20rotation%20be%20obtained%20with%20a%20transpose%2C%20while%20reversing%20a%20product%20also%20requires%20reversing%20the%20factor%20order%3F%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%20Orthogonality%20gives%20%24R%5E%7B-1%7D%3DR%5ET%24.%20For%20%24R%3DR_zR_yR_x%24%2C%20the%20inverse%20is%20%24R_x%5ETR_y%5ETR_z%5ET%24%3A%20the%20last%20operation%20must%20be%20undone%20first.%20Keeping%20the%20original%20factor%20order%20would%20generally%20give%20another%20orientation.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20**Exercise%203.**%20A%20matrix%20passes%20%24R%5ETR%3DI%24%20but%20has%20determinant%20%E2%88%921.%20Can%20its%20entries%20be%20treated%20as%20an%20anatomical%20rotation%3F%20What%20if%20the%20middle%20Cardan%20angle%20is%2090%C2%B0%3F%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%20Determinant%20%E2%88%921%20means%20a%20reflection%2C%20so%20one%20axis%20convention%20must%20be%20corrected%20before%20calling%20it%20a%20rotation.%20At%20a%2090%C2%B0%20middle%20angle%20in%20this%20Cardan%20convention%2C%20the%20orientation%20matrix%20remains%20valid%2C%20but%20two%20angle%20coordinates%20become%20coupled%3A%20separate%20first%20and%20third%20angles%20are%20not%20unique.%20This%20is%20a%20coordinate%20singularity%2C%20not%20a%20loss%20of%20physical%20orientation.%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%201.%20What%20properties%20distinguish%20a%20rotation%20from%20scaling%3F%0A%20%20%20%202.%20Does%20transposing%20a%20rotation%20undo%20it%3F%0A%20%20%20%203.%20Are%20three%20orthogonal%20unit%20vectors%20automatically%20right-handed%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Checkpoint%20answers%0A%0A%20%20%20%201.%20A%20rotation%20preserves%20lengths%20and%20angles%20and%20has%20determinant%20%2B1.%20Scaling%20generally%20changes%20lengths.%202.%20Yes%2C%20for%20a%20proper%20orthogonal%20rotation%20matrix.%203.%20No%3B%20the%20determinant%20must%20also%20be%20%2B1.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%20Problems%0A%0A%20%20%20%201.%20Rotate%20%24(0%2C1%2C0)%24%20by%20%2460%5E%5Ccirc%24%20about%20the%20fixed%20positive%20%24x%24%20axis.%0A%20%20%20%202.%20Give%20the%20ellipsoid%E2%80%99s%20volume%20and%20say%20whether%20rotation%20changes%20it.%0A%20%20%20%203.%20Let%20%24R%3DR_z(90%5E%5Ccirc)R_x(90%5E%5Ccirc)%24.%20Give%20%24R(0%2C1%2C0)%24%20and%20compare%20it%20with%20the%20reversed%20order.%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Final%20answers%20to%20the%20problems%0A%0A%20%20%20%201.%20%24(0%2C1%2F2%2C%5Csqrt3%2F2)%24.%0A%20%20%20%202.%20%244%5Cpi%2F(3%5Csqrt%7B45%7D)%5Capprox0.6244%24%20cubic%20coordinate%20units%3B%20unchanged.%0A%20%20%20%203.%20%24(0%2C0%2C1)%24%3B%20the%20reversed%20order%20gives%20%24(-1%2C0%2C0)%24.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%20Go%20deeper%0A%0A%20%20%20%20%5BTransformation3D%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Ftransformation_3d.py)%20develops%20active%2Fpassive%20conventions%20and%20sequence-dependent%20angles.%20%5BCoordinateSystem%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fcoordinate_system.py)%20connects%20the%20marker%20calculations%20below%20the%20surfaces%20to%20anatomical%20frames.%0A%0A%20%20%20%20%23%23%23%20Video%20lectures%20on%20the%20Internet%0A%0A%20%20%20%20%5BLynch%20and%20Park%3A%20rotation%20matrices%5D(https%3A%2F%2Fmodernrobotics.northwestern.edu%2Fnu-gm-book-resource%2F3-2-1-rotation-matrices-part-1-of-2%2F)%20explains%20the%20orthogonality%20and%20determinant%20tests%20used%20here.%0A%0A%20%20%20%20%23%23%20References%0A%0A%20%20%20%20-%20Lynch%20KM%2C%20Park%20FC%2C%20*Modern%20Robotics*%2C%20Chapter%203%3A%20rotation%20matrices%20and%20rigid%20configurations.%0A%0A%20%20%20%20-%20Original%20BMC%20ellipsoid%20and%20marker%20examples%2C%20preserved%20from%20the%20paired%20Jupyter%20notebook.%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
fdc38d1b40ae3a01237f5669223c8208