|
37 | 37 | "r_cham_out": 2e-2 - 2e-3 * jnp.ones((num_segments,)),
|
38 | 38 | "varphi_cham": jnp.pi/2 * jnp.ones((num_segments,)),
|
39 | 39 | }
|
40 |
| -params["D"] = 1e-3 * jnp.diag( |
| 40 | +params["D"] = 5e-4 * jnp.diag( |
41 | 41 | (jnp.repeat(
|
42 | 42 | jnp.array([[1e0, 1e3, 1e3]]), num_segments, axis=0
|
43 | 43 | ) * params["l"][:, None]).flatten()
|
|
52 | 52 | )
|
53 | 53 | # jit the functions
|
54 | 54 | dynamical_matrices_fn = jax.jit(dynamical_matrices_fn)
|
55 |
| -actuation_mapping_fn = auxiliary_fns["actuation_mapping_fn"] |
| 55 | +actuation_mapping_fn = partial( |
| 56 | + auxiliary_fns["actuation_mapping_fn"], |
| 57 | + forward_kinematics_fn, |
| 58 | + auxiliary_fns["jacobian_fn"], |
| 59 | +) |
56 | 60 |
|
57 | 61 | def sweep_actuation_mapping():
|
| 62 | + # evaluate the actuation matrix for a straight backbone |
58 | 63 | q = jnp.zeros((2 * num_segments,))
|
59 | 64 | A = actuation_mapping_fn(params, B_xi, q)
|
60 |
| - print("A =\n", A) |
| 65 | + print("Evaluating actuation matrix for straight backbone: A =\n", A) |
| 66 | + |
| 67 | + kappa_be_pts = jnp.linspace(-jnp.pi, jnp.pi, 500) |
| 68 | + sigma_ax_pts = jnp.zeros_like(kappa_be_pts) |
| 69 | + q_pts = jnp.stack([kappa_be_pts, sigma_ax_pts], axis=-1) |
| 70 | + A_pts = vmap(actuation_mapping_fn, in_axes=(None, None, 0))(params, B_xi, q_pts) |
| 71 | + # plot the mapping on the bending strain for various bending strains |
| 72 | + fig, ax = plt.subplots(num="pneumatic_planar_pcs_actuation_mapping_bending_torque_vs_bending_strain") |
| 73 | + plt.title(r"Actuation mapping from $u_1$ to $\tau_\mathrm{be}$") |
| 74 | + ax.plot(kappa_be_pts, A_pts[:, 0, 0], linewidth=2) |
| 75 | + # shade the region where the actuation mapping is negative as we are not able to bend the robot further |
| 76 | + ax.axhspan(A_pts[:, 0, 0].min(), 0.0, facecolor='red', alpha=0.5) |
| 77 | + ax.set_xlabel(r"$\kappa_\mathrm{be}$ [rad/m]") |
| 78 | + ax.set_ylabel(r"$\frac{\partial \tau_\mathrm{be}}{\partial u_1}$") |
| 79 | + plt.grid(True) |
| 80 | + plt.tight_layout() |
| 81 | + plt.show() |
| 82 | + |
| 83 | + # create grid for bending and axial strains |
| 84 | + kappa_be_grid, sigma_ax_grid = jnp.meshgrid( |
| 85 | + jnp.linspace(-jnp.pi, jnp.pi, 20), |
| 86 | + jnp.linspace(-0.2, 0.2, 20), |
| 87 | + ) |
| 88 | + q_pts = jnp.stack([kappa_be_grid.flatten(), sigma_ax_grid.flatten()], axis=-1) |
| 89 | + |
| 90 | + # evaluate the actuation mapping on the grid |
| 91 | + A_pts = vmap(actuation_mapping_fn, in_axes=(None, None, 0))(params, B_xi, q_pts) |
| 92 | + # reshape A_pts to match the grid shape |
| 93 | + A_grid = A_pts.reshape(kappa_be_grid.shape[:2] + A_pts.shape[-2:]) |
| 94 | + |
| 95 | + # plot the mapping on the bending strain |
| 96 | + fig, ax = plt.subplots(num="pneumatic_planar_pcs_actuation_mapping_bending_torque_vs_axial_vs_bending_strain") |
| 97 | + plt.title(r"Actuation mapping from $u_1$ to $\tau_\mathrm{be}$") |
| 98 | + # contourf plot |
| 99 | + c = ax.contourf(kappa_be_grid, sigma_ax_grid, A_grid[..., 0, 0], levels=100) |
| 100 | + fig.colorbar(c, ax=ax, label=r"$\frac{\partial \tau_\mathrm{be}}{\partial u_1}$") |
| 101 | + # contour plot |
| 102 | + ax.contour(kappa_be_grid, sigma_ax_grid, A_grid[..., 0, 0], levels=20, colors="k", linewidths=0.5) |
| 103 | + ax.set_xlabel(r"$\kappa_\mathrm{be}$ [rad/m]") |
| 104 | + ax.set_ylabel(r"$\sigma_\mathrm{ax}$ [-]") |
| 105 | + plt.tight_layout() |
| 106 | + plt.show() |
| 107 | + |
| 108 | + # plot the mapping on the axial strain |
| 109 | + fig, ax = plt.subplots(num="pneumatic_planar_pcs_actuation_mapping_axial_torque_vs_axial_vs_bending_strain") |
| 110 | + plt.title(r"Actuation mapping from $u_1$ to $\tau_\mathrm{ax}$") |
| 111 | + # contourf plot |
| 112 | + c = ax.contourf(kappa_be_grid, sigma_ax_grid, A_grid[..., 1, 0], levels=100) |
| 113 | + fig.colorbar(c, ax=ax, label=r"$\frac{\partial \tau_\mathrm{ax}}{\partial u_1}$") |
| 114 | + # contour plot |
| 115 | + ax.contour(kappa_be_grid, sigma_ax_grid, A_grid[..., 1, 0], levels=20, colors="k", linewidths=0.5) |
| 116 | + ax.set_xlabel(r"$\kappa_\mathrm{be}$ [rad/m]") |
| 117 | + ax.set_ylabel(r"$\sigma_\mathrm{ax}$ [-]") |
| 118 | + plt.tight_layout() |
| 119 | + plt.show() |
61 | 120 |
|
62 | 121 |
|
63 | 122 | def simulate_robot():
|
64 | 123 | # define initial configuration
|
65 |
| - q0 = jnp.repeat(jnp.array([5.0 * jnp.pi, 0.2])[None, :], num_segments, axis=0).flatten() |
| 124 | + q0 = jnp.repeat(jnp.array([-5.0 * jnp.pi, -0.2])[None, :], num_segments, axis=0).flatten() |
66 | 125 | # number of generalized coordinates
|
67 | 126 | n_q = q0.shape[0]
|
68 | 127 |
|
69 | 128 | # set simulation parameters
|
70 | 129 | dt = 1e-3 # time step
|
71 | 130 | sim_dt = 5e-5 # simulation time step
|
72 |
| - ts = jnp.arange(0.0, 2, dt) # time steps |
| 131 | + ts = jnp.arange(0.0, 7.0, dt) # time steps |
73 | 132 |
|
74 | 133 | x0 = jnp.concatenate([q0, jnp.zeros_like(q0)]) # initial condition
|
75 |
| - tau = jnp.zeros_like(q0) # torques |
| 134 | + u = jnp.array([1.2e3, 0e0]) # control inputs (pressures in the right and left chambers) |
76 | 135 |
|
77 |
| - ode_fn = ode_factory(dynamical_matrices_fn, params, tau) |
| 136 | + ode_fn = ode_factory(dynamical_matrices_fn, params, u) |
78 | 137 | term = ODETerm(ode_fn)
|
79 | 138 |
|
80 | 139 | sol = diffeqsolve(
|
|
0 commit comments