|
| 1 | +import biorbd |
| 2 | +import math |
| 3 | + |
| 4 | +import matplotlib.pyplot as plt |
| 5 | +import numpy as np |
| 6 | +from mpl_toolkits.mplot3d import Axes3D |
| 7 | + |
| 8 | +# functions for cylinder rotation |
| 9 | +def cyl2cart(r, theta, z): |
| 10 | + return (r*np.cos(theta), r*np.sin(theta), z) |
| 11 | + |
| 12 | + |
| 13 | +def roll(R, zi, zf, RT): |
| 14 | + t = np.arange(0, 2 * np.pi + 0.1, 0.1) |
| 15 | + z = np.array([zi, zf]) |
| 16 | + t, z = np.meshgrid(t, z) |
| 17 | + p, q = t.shape |
| 18 | + r = R * np.ones([p, q], float) |
| 19 | + # cylindrical coordinates to Cartesian coordinate |
| 20 | + x, y, z = cyl2cart(r, t, z) |
| 21 | + |
| 22 | + # Euler rotation |
| 23 | + rot = np.dot( |
| 24 | + RT.rot().to_array(), |
| 25 | + np.array([x.ravel(), y.ravel(), z.ravel()]) |
| 26 | + ) |
| 27 | + |
| 28 | + x_rt = rot[0, :].reshape(x.shape) + RTw.trans().to_array()[0] |
| 29 | + y_rt = rot[1, :].reshape(y.shape) + RTw.trans().to_array()[1] |
| 30 | + z_rt = rot[2, :].reshape(z.shape) + RTw.trans().to_array()[2] |
| 31 | + |
| 32 | + return x_rt, y_rt, z_rt, |
| 33 | + |
| 34 | +# model |
| 35 | +model = biorbd.Model("WrappingObjectExample.bioMod") |
| 36 | + |
| 37 | +# wrapping RT matrix |
| 38 | +RTw = biorbd.WrappingCylinder( |
| 39 | + model.muscle(0).pathModifier().object(0)).RT(model, np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1])) |
| 40 | +RTw_trans = RTw.transpose() |
| 41 | + |
| 42 | +# Point in global base |
| 43 | +Po = [0.264534159209888, 0.08668973339838759, 0.4024172540921048] |
| 44 | +Pi = [0.24035592212771023, 0.36899416468322876, 0.8650273094461659] |
| 45 | +Pi_wrap = [0.28997869688863276, 0.34739632020407846, 0.6636920365713757] |
| 46 | +Po_wrap = [0.29330355695193333, 0.3289556960274852, 0.627410425452938] |
| 47 | + |
| 48 | +# Plot the surface |
| 49 | +fig = plt.figure() |
| 50 | +ax = fig.add_subplot(111, projection='3d') |
| 51 | +x, y, z = roll(0.05, -0.2, 0.2, RTw) |
| 52 | +ax.plot_surface(x, y, z) |
| 53 | +plt.plot((Po[0], Po_wrap[0]), (Po[1], Po_wrap[1]), (Po[2], Po_wrap[2]), marker='o') |
| 54 | +plt.plot((Pi[0], Pi_wrap[0]), (Pi[1], Pi_wrap[1]), (Pi[2], Pi_wrap[2]), marker='o') |
| 55 | + |
| 56 | +# To set Axe3D to (almost) equal |
| 57 | +max_range = np.array([x.max()-x.min(), y.max()-y.min(), z.max()-z.min()]).max() |
| 58 | +Xb = 0.5*max_range*np.mgrid[-1:2:2, -1:2:2, -1:2:2][0].flatten() + 0.5*(x.max()+x.min()) |
| 59 | +Yb = 0.5*max_range*np.mgrid[-1:2:2, -1:2:2, -1:2:2][1].flatten() + 0.5*(y.max()+y.min()) |
| 60 | +Zb = 0.5*max_range*np.mgrid[-1:2:2, -1:2:2, -1:2:2][2].flatten() + 0.5*(z.max()+z.min()) |
| 61 | +for xb, yb, zb in zip(Xb, Yb, Zb): |
| 62 | + ax.plot([xb], [yb], [zb], 'w') |
| 63 | +plt.show() |
| 64 | + |
| 65 | +# Compute muscle length |
| 66 | +r = biorbd.WrappingCylinder(model.muscle(0).pathModifier().object(0)).radius() |
| 67 | +l_muscle_bd = model.muscle(0).musculoTendonLength(model, np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1])) |
| 68 | + |
| 69 | + |
| 70 | +l_wt_arc = np.sqrt((Po_wrap[0]-Po[0])**2 + (Po_wrap[1]-Po[1])**2 + (Po_wrap[2]-Po[2])**2) + np.sqrt((Pi_wrap[0]-Pi[0])**2 + (Pi_wrap[1]-Pi[1])**2 + (Pi_wrap[2]-Pi[2])**2) |
| 71 | + |
| 72 | +# Pi_wrap and Po_wrap provide in wrapping base to compute arc length |
| 73 | +Pi_wrap = biorbd.Vector3d(0.28997869688863276, 0.34739632020407846, 0.6636920365713757) |
| 74 | +Pi_wrap.applyRT(RTw_trans) |
| 75 | +Pi_wrap = Pi_wrap.to_array() |
| 76 | + |
| 77 | +Po_wrap = biorbd.Vector3d(0.29330355695193333, 0.3289556960274852, 0.627410425452938) |
| 78 | +Po_wrap.applyRT(RTw_trans) |
| 79 | +Po_wrap = Po_wrap.to_array() |
| 80 | + |
| 81 | +arc = math.acos( |
| 82 | + ((Po_wrap[0] * Pi_wrap[0]) + (Pi_wrap[1] * Po_wrap[1])) / ( |
| 83 | + math.sqrt(((Pi_wrap[1]**2)+(Pi_wrap[0]**2)) * ((Po_wrap[1]**2) + (Po_wrap[0]**2))))) * r |
| 84 | + |
| 85 | +l_arc = math.sqrt(arc**2 + (Po_wrap[2]-Pi_wrap[2])**2) |
| 86 | + |
| 87 | +l_m = l_wt_arc + l_arc # l_m = 0.582246096069153 |
0 commit comments