Skip to content

Commit 231c9e3

Browse files
committed
Change fori_loop to vmap/scan and cond to min in
the planar_pcs_num.py file. Correct a description of function in the planar_pcs.py file.
1 parent ab00835 commit 231c9e3

File tree

5 files changed

+119
-116
lines changed

5 files changed

+119
-116
lines changed

examples/simulate_planar_pcs.py

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,19 @@
1717

1818
import time
1919

20+
# ==================================================
21+
# Simulation parameters
22+
# ==================================================
2023
num_segments = 2
2124

2225
type_of_derivation = "numeric" #"symbolic" #
26+
type_of_integration = "trapezoid" #"gauss" #
27+
28+
if type_of_derivation == "numeric":
29+
if type_of_integration == "gauss":
30+
param_integration = 30
31+
elif type_of_integration == "trapezoid":
32+
param_integration = 100
2333

2434
if type_of_derivation == "symbolic":
2535
# filepath to symbolic expressions
@@ -59,13 +69,20 @@
5969
# ======================
6070
# set simulation parameters
6171
dt = 1e-4 # time step
62-
ts = jnp.arange(0.0, 2, dt) # time steps
72+
ts = jnp.arange(0.0, 1, dt) # time steps
6373
skip_step = 10 # how many time steps to skip in between video frames
6474
video_ts = ts[::skip_step] # time steps for video
6575

6676
# video settings
67-
video_width, video_height = 700, 700 # img height and width
68-
video_path = Path(__file__).parent / "videos" / f"planar_pcs_ns-{num_segments}-{('symb' if type_of_derivation == 'symbolic' else 'num')}.mp4"
77+
video_width, video_height = 700, 700 # img height and width"
78+
video_path_parent = Path(__file__).parent / "videos"
79+
video_path_parent.mkdir(parents=True, exist_ok=True)
80+
extension = f"planar_pcs_ns-{num_segments}-{('symb' if type_of_derivation == 'symbolic' else 'num')}"
81+
if type_of_derivation == "numeric":
82+
extension += f"-{type_of_integration}-{param_integration}"
83+
elif type_of_derivation == "symbolic":
84+
extension += "-symb"
85+
video_path = video_path_parent / f"{extension}.mp4"
6986

7087
def draw_robot(
7188
batched_forward_kinematics_fn: Callable,
@@ -107,28 +124,33 @@ def draw_robot(
107124
# ======================
108125
figures_path_parent = Path(__file__).parent / "figures"
109126
extension = f"planar_pcs_ns-{num_segments}-{('symb' if type_of_derivation == 'symbolic' else 'num')}"
127+
if type_of_derivation == "numeric":
128+
extension += f"-{type_of_integration}-{param_integration}"
110129
figures_path_parent.mkdir(parents=True, exist_ok=True)
111130

112131
if __name__ == "__main__":
113132
print("Type of derivation:", type_of_derivation)
133+
if type_of_derivation == "numeric":
134+
print("Type of integration:", type_of_integration)
135+
print("Parameter for integration:", param_integration)
114136
print("Number of segments:", num_segments, "\n")
115137

116138
print("Importing the planar PCS model...")
117139
timer_start = time.time()
118-
# import jsrm
119140
if type_of_derivation == "symbolic":
120141
strain_basis, forward_kinematics_fn, dynamical_matrices_fn, auxiliary_fns = (
121142
planar_pcs.factory(sym_exp_filepath, strain_selector)
122143
)
123144

124145
elif type_of_derivation == "numeric":
125146
strain_basis, forward_kinematics_fn, dynamical_matrices_fn, auxiliary_fns = (
126-
planar_pcs_num.factory(num_segments, strain_selector)
147+
planar_pcs_num.factory(num_segments, strain_selector, integration_type=type_of_integration, param_integration=param_integration)
127148
)
128149
else:
129150
raise ValueError("type_of_derivation must be 'symbolic' or 'numeric'")
130151

131152
# jit the functions
153+
print("JIT-compiling the dynamical matrices function ...")
132154
dynamical_matrices_fn = jax.jit(partial(dynamical_matrices_fn))
133155
batched_forward_kinematics = vmap(
134156
forward_kinematics_fn, in_axes=(None, None, 0), out_axes=-1
@@ -148,42 +170,51 @@ def draw_robot(
148170
timer_end = time.time()
149171
print(f"Evaluating the dynamical matrices took {timer_end - timer_start:.2f} seconds. \n")
150172

173+
# Parameter for the simulation
151174
x0 = jnp.concatenate([q0, jnp.zeros_like(q0)]) # initial condition
152175
tau = jnp.zeros_like(q0) # torques
153176

154-
timer_start = time.time()
155177
ode_fn = ode_factory(dynamical_matrices_fn, params, tau)
156178
term = ODETerm(ode_fn)
157-
timer_end = time.time()
158179

159-
print("Solving the ODE...")
180+
# jit the functions
181+
print("JIT-compiling the ODE function...")
182+
diffeqsolve_fn = jax.jit(
183+
partial(diffeqsolve,
184+
term,
185+
solver=Tsit5(),
186+
t0=ts[0],
187+
t1=ts[-1],
188+
dt0=dt,
189+
y0=x0,
190+
max_steps=None,
191+
saveat=SaveAt(ts=video_ts)))
192+
193+
print("Solving the ODE for the first time (JIT-compilation)...")
160194
timer_start = time.time()
161-
sol = diffeqsolve(
162-
term,
163-
solver=Tsit5(),
164-
t0=ts[0],
165-
t1=ts[-1],
166-
dt0=dt,
167-
y0=x0,
168-
max_steps=None,
169-
saveat=SaveAt(ts=video_ts),
170-
)
171-
195+
sol = diffeqsolve_fn()
172196
print("sol.ys =\n", sol.ys)
197+
timer_end = time.time()
173198
# the evolution of the generalized coordinates
174199
q_ts = sol.ys[:, :n_q]
175200
# the evolution of the generalized velocities
176201
q_d_ts = sol.ys[:, n_q:]
202+
print(f"Solving the ODE took {timer_end - timer_start:.2f} seconds. \n")
177203

204+
print("Solving the ODE for the second time (after JIT-compilation)...")
205+
timer_start = time.time()
206+
sol = diffeqsolve_fn()
207+
print("sol.ys =\n", sol.ys)
178208
timer_end = time.time()
179-
print(f"Solving the ODE took {timer_end - timer_start:.2f} seconds. \n")
209+
print(f"Solving the ODE for a second time took {timer_end - timer_start:.2f} seconds. \n")
180210

181211
print("Evaluating the forward kinematics...")
182212
timer_start = time.time()
183213
# evaluate the forward kinematics along the trajectory
184214
chi_ee_ts = vmap(forward_kinematics_fn, in_axes=(None, 0, None))(
185215
params, q_ts, jnp.array([jnp.sum(params["l"])])
186216
)
217+
print("chi_ee_ts =\n", chi_ee_ts)
187218
timer_end = time.time()
188219
print(f"Evaluating the forward kinematics took {timer_end - timer_start:.2f} seconds. ")
189220

@@ -264,7 +295,6 @@ def draw_robot(
264295
# plot the energy vs time
265296
plt.figure()
266297
plt.title("Energy vs Time")
267-
plt.plot(video_ts, U_ts + T_ts, label="Total energy")
268298
plt.plot(video_ts, U_ts, label="Potential energy")
269299
plt.plot(video_ts, T_ts, label="Kinetic energy")
270300
plt.xlabel("Time [s]")
@@ -283,7 +313,6 @@ def draw_robot(
283313
timer_start = time.time()
284314
# create video
285315
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
286-
video_path.parent.mkdir(parents=True, exist_ok=True)
287316
video = cv2.VideoWriter(
288317
str(video_path),
289318
fourcc,
-406 Bytes
Binary file not shown.
-5.83 KB
Binary file not shown.

src/jsrm/systems/planar_pcs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ def operational_space_dynamical_matrices_fn(
472472
Lambda: inertia matrix in the operational space of shape (3, 3)
473473
mu: matrix with corioli and centrifugal terms in the operational space of shape (3, 3)
474474
J: Jacobian of the Cartesian pose with respect to the generalized coordinates of shape (3, n_q)
475-
J: time-derivative of the Jacobian of the end-effector pose with respect to the generalized coordinates
475+
J_d: time-derivative of the Jacobian of the end-effector pose with respect to the generalized coordinates
476476
of shape (3, n_q)
477477
JB_pinv: Dynamically-consistent pseudo-inverse of the Jacobian. Allows the mapping of torques
478478
from the generalized coordinates to the operational space: f = JB_pinv.T @ tau_q

0 commit comments

Comments
 (0)