1 """This script is a slight variation of ex_4_walking.py introduced to test the new
2 center of pressure (CoP) task. In this script, besides tracking a reference
3 center of mass (CoM), the TSID controller also tries to track a reference CoP.
4 The resulting motion doesn't look great because the reference CoP is an open-loop
5 reference trajectory, so it is not stabilizing, and it conflicts with the CoM task.
6 However, the results show that the CoP is tracked reasonably well during the motion,
7 which was the goal of the test, validating the CoP task.
12 import ex_4_conf
as conf
13 import matplotlib.pyplot
as plt
15 import plot_utils
as plut
17 from numpy.linalg
import norm
as norm
20 from tsid_biped
import TsidBiped
22 print(
"".
center(conf.LINE_WIDTH,
"#"))
23 print(
" Test Walking ".
center(conf.LINE_WIDTH,
"#"))
24 print(
"".
center(conf.LINE_WIDTH,
"#"),
"\n")
32 data = np.load(conf.DATA_FILE_TSID)
36 N = data[
"com"].shape[1]
37 N_pre = int(conf.T_pre / conf.dt)
38 N_post = int(conf.T_post / conf.dt)
40 com_pos = np.empty((3, N + N_post)) * nan
41 com_vel = np.empty((3, N + N_post)) * nan
42 com_acc = np.empty((3, N + N_post)) * nan
43 x_LF = np.empty((3, N + N_post)) * nan
44 dx_LF = np.empty((3, N + N_post)) * nan
45 ddx_LF = np.empty((3, N + N_post)) * nan
46 ddx_LF_des = np.empty((3, N + N_post)) * nan
47 x_RF = np.empty((3, N + N_post)) * nan
48 dx_RF = np.empty((3, N + N_post)) * nan
49 ddx_RF = np.empty((3, N + N_post)) * nan
50 ddx_RF_des = np.empty((3, N + N_post)) * nan
51 f_RF = np.zeros((6, N + N_post))
52 f_LF = np.zeros((6, N + N_post))
53 cop_RF = np.zeros((2, N + N_post))
54 cop_LF = np.zeros((2, N + N_post))
55 cop = np.zeros((2, N + N_post))
56 tau = np.zeros((tsid.robot.na, N + N_post))
57 q_log = np.zeros((tsid.robot.nq, N + N_post))
58 v_log = np.zeros((tsid.robot.nv, N + N_post))
60 contact_phase = data[
"contact_phase"]
61 com_pos_ref = np.asarray(data[
"com"])
62 com_vel_ref = np.asarray(data[
"dcom"])
63 com_acc_ref = np.asarray(data[
"ddcom"])
64 x_RF_ref = np.asarray(data[
"x_RF"])
65 dx_RF_ref = np.asarray(data[
"dx_RF"])
66 ddx_RF_ref = np.asarray(data[
"ddx_RF"])
67 x_LF_ref = np.asarray(data[
"x_LF"])
68 dx_LF_ref = np.asarray(data[
"dx_LF"])
69 ddx_LF_ref = np.asarray(data[
"ddx_LF"])
70 cop_ref = np.asarray(data[
"cop"])
72 np.empty((3, N + N_post)) * nan
75 x_rf = tsid.get_placement_RF().translation
76 offset = x_rf - x_RF_ref[:, 0]
78 com_pos_ref[:, i] += offset + np.array([0.0, 0.0, 0.0])
79 cop_ref[:, i] += offset[:2]
80 x_RF_ref[:, i] += offset
81 x_LF_ref[:, i] += offset
83 cop_ref[:, -1] = cop_ref[:, -2]
88 for i
in range(-N_pre, N + N_post):
89 time_start = time.time()
92 print(
"Starting to walk (remove contact left foot)")
93 tsid.remove_contact_LF()
95 tsid.formulation.updateTaskWeight(tsid.copTask.name, 1e-4)
96 elif i > 0
and i < N - 1:
97 if contact_phase[i] != contact_phase[i - 1]:
99 f
"Time {t:.3f} Changing contact phase from {contact_phase[i - 1]} to {contact_phase[i]}"
101 if contact_phase[i] ==
"left":
102 tsid.add_contact_LF()
103 tsid.remove_contact_RF()
105 tsid.add_contact_RF()
106 tsid.remove_contact_LF()
109 if contact_phase[i - 1] ==
"left":
110 tsid.add_contact_RF()
112 tsid.add_contact_LF()
116 com_pos_ref[:, 0], 0 * com_vel_ref[:, 0], 0 * com_acc_ref[:, 0]
119 tsid.set_com_ref(com_pos_ref[:, i], com_vel_ref[:, i], com_acc_ref[:, i])
120 tsid.set_LF_3d_ref(x_LF_ref[:, i], dx_LF_ref[:, i], ddx_LF_ref[:, i])
121 tsid.set_RF_3d_ref(x_RF_ref[:, i], dx_RF_ref[:, i], ddx_RF_ref[:, i])
122 tsid.copTask.setReference(np.concatenate([cop_ref[:, i], np.zeros(1)]))
124 HQPData = tsid.formulation.computeProblemData(t, q, v)
126 sol = tsid.solver.solve(HQPData)
128 print(
"QP problem could not be solved! Error code:", sol.status)
130 if norm(v, 2) > 40.0:
131 print(f
"Time {t:.3f} Velocities are too high, stop everything!", norm(v))
137 tau[:, i] = tsid.formulation.getActuatorForces(sol)
138 dv = tsid.formulation.getAccelerations(sol)
141 com_pos[:, i] = tsid.robot.com(tsid.formulation.data())
142 com_vel[:, i] = tsid.robot.com_vel(tsid.formulation.data())
143 com_acc[:, i] = tsid.comTask.getAcceleration(dv)
144 com_acc_des[:, i] = tsid.comTask.getDesiredAcceleration
145 x_LF[:, i], dx_LF[:, i], ddx_LF[:, i] = tsid.get_LF_3d_pos_vel_acc(dv)
146 if not tsid.contact_LF_active:
147 ddx_LF_des[:, i] = tsid.leftFootTask.getDesiredAcceleration[:3]
148 x_RF[:, i], dx_RF[:, i], ddx_RF[:, i] = tsid.get_RF_3d_pos_vel_acc(dv)
149 if not tsid.contact_RF_active:
150 ddx_RF_des[:, i] = tsid.rightFootTask.getDesiredAcceleration[:3]
152 if tsid.formulation.checkContact(tsid.contactRF.name, sol):
153 T_RF = tsid.contactRF.getForceGeneratorMatrix
154 f_RF[:, i] = T_RF.dot(
155 tsid.formulation.getContactForce(tsid.contactRF.name, sol)
157 if f_RF[2, i] > 1e-3:
158 cop_RF[0, i] = f_RF[4, i] / f_RF[2, i]
159 cop_RF[1, i] = -f_RF[3, i] / f_RF[2, i]
160 if tsid.formulation.checkContact(tsid.contactLF.name, sol):
161 T_LF = tsid.contactRF.getForceGeneratorMatrix
162 f_LF[:, i] = T_LF.dot(
163 tsid.formulation.getContactForce(tsid.contactLF.name, sol)
165 if f_LF[2, i] > 1e-3:
166 cop_LF[0, i] = f_LF[4, i] / f_LF[2, i]
167 cop_LF[1, i] = -f_LF[3, i] / f_LF[2, i]
168 cop_LF_world = tsid.get_placement_LF().act(
169 np.array([cop_LF[0, i], cop_LF[1, i], 0])
171 cop_RF_world = tsid.get_placement_RF().act(
172 np.array([cop_RF[0, i], cop_RF[1, i], 0])
174 cop[:, i] = (cop_LF_world[:2] * f_LF[2, i] + cop_RF_world[:2] * f_RF[2, i]) / (
175 f_LF[2, i] + f_RF[2, i]
178 if i % conf.PRINT_N == 0:
179 print(f
"Time {t:.3f}")
180 if tsid.formulation.checkContact(tsid.contactRF.name, sol)
and i >= 0:
182 "\tnormal force {}: {:.1f}".format(
183 tsid.contactRF.name.ljust(20,
"."), f_RF[2, i]
187 if tsid.formulation.checkContact(tsid.contactLF.name, sol)
and i >= 0:
189 "\tnormal force {}: {:.1f}".format(
190 tsid.contactLF.name.ljust(20,
"."), f_LF[2, i]
195 "\ttracking err {}: {:.3f}".format(
196 tsid.comTask.name.ljust(20,
"."), norm(tsid.comTask.position_error, 2)
199 print(f
"\t||v||: {norm(v, 2):.3f}\t ||dv||: {norm(dv):.3f}")
201 q, v = tsid.integrate_dv(q, v, dv, conf.dt)
204 if i % conf.DISPLAY_N == 0:
207 time_spent = time.time() - time_start
208 if time_spent < conf.dt:
209 time.sleep(conf.dt - time_spent)
212 time = np.arange(0.0, (N + N_post) * conf.dt, conf.dt)
215 (f, ax) = plut.create_empty_figure(3, 1)
217 ax[i].
plot(time, com_pos[i, :], label=
"CoM " + str(i))
218 ax[i].
plot(time[:N], com_pos_ref[i, :],
"r:", label=
"CoM Ref " + str(i))
219 ax[i].set_xlabel(
"Time [s]")
220 ax[i].set_ylabel(
"CoM [m]")
222 leg.get_frame().set_alpha(0.5)
224 (f, ax) = plut.create_empty_figure(3, 1)
226 ax[i].
plot(time, com_vel[i, :], label=
"CoM Vel " + str(i))
227 ax[i].
plot(time[:N], com_vel_ref[i, :],
"r:", label=
"CoM Vel Ref " + str(i))
228 ax[i].set_xlabel(
"Time [s]")
229 ax[i].set_ylabel(
"CoM Vel [m/s]")
231 leg.get_frame().set_alpha(0.5)
233 (f, ax) = plut.create_empty_figure(3, 1)
235 ax[i].
plot(time, com_acc[i, :], label=
"CoM Acc " + str(i))
236 ax[i].
plot(time[:N], com_acc_ref[i, :],
"r:", label=
"CoM Acc Ref " + str(i))
237 ax[i].
plot(time, com_acc_des[i, :],
"g--", label=
"CoM Acc Des " + str(i))
238 ax[i].set_xlabel(
"Time [s]")
239 ax[i].set_ylabel(
"CoM Acc [m/s^2]")
241 leg.get_frame().set_alpha(0.5)
244 (f, ax) = plut.create_empty_figure(2, 1)
246 ax[i].
plot(time, cop_LF[i, :], label=
"CoP LF " + str(i))
247 ax[i].
plot(time, cop_RF[i, :], label=
"CoP RF " + str(i))
251 [-conf.lxn, -conf.lxn],
253 label=
"CoP Lim " + str(i),
257 [conf.lxp, conf.lxp],
259 label=
"CoP Lim " + str(i),
264 [-conf.lyn, -conf.lyn],
266 label=
"CoP Lim " + str(i),
270 [conf.lyp, conf.lyp],
272 label=
"CoP Lim " + str(i),
274 ax[i].set_xlabel(
"Time [s]")
275 ax[i].set_ylabel(
"CoP (local) [m]")
277 leg.get_frame().set_alpha(0.5)
279 (f, ax) = plut.create_empty_figure(2, 1)
281 ax[i].
plot(time[:N], cop_ref[i, :], label=
"CoP ref " + str(i))
282 ax[i].
plot(time, cop[i, :], label=
"CoP " + str(i))
283 ax[i].set_xlabel(
"Time [s]")
284 ax[i].set_ylabel(
"CoP (world) [m]")
286 leg.get_frame().set_alpha(0.5)
301 plt.plot(time, x_RF[i, :], label=
"x RF " + str(i))
302 plt.plot(time[:N], x_RF_ref[i, :],
":", label=
"x RF ref " + str(i))
303 plt.plot(time, x_LF[i, :], label=
"x LF " + str(i))
304 plt.plot(time[:N], x_LF_ref[i, :],
":", label=
"x LF ref " + str(i))
327 for i
in range(tsid.robot.na):
329 2 * (tau[i, :] - tsid.tau_min[i]) / (tsid.tau_max[i] - tsid.tau_min[i]) - 1
332 if np.max(np.abs(tau_normalized)) > 0.5:
333 plt.plot(time, tau_normalized, alpha=0.5, label=tsid.model.names[i + 2])
334 plt.plot([time[0], time[-1]], 2 * [-1.0],
":")
335 plt.plot([time[0], time[-1]], 2 * [1.0],
":")
336 plt.gca().set_xlabel(
"Time [s]")
337 plt.gca().set_ylabel(
"Normalized Torque")
339 leg.get_frame().set_alpha(0.5)
343 for i
in range(tsid.robot.na):
345 2 * (v_log[6 + i, :] - tsid.v_min[i]) / (tsid.v_max[i] - tsid.v_min[i]) - 1
348 if np.max(np.abs(v_normalized)) > 0.5:
349 plt.plot(time, v_normalized, alpha=0.5, label=tsid.model.names[i + 2])
350 plt.plot([time[0], time[-1]], 2 * [-1.0],
":")
351 plt.plot([time[0], time[-1]], 2 * [1.0],
":")
352 plt.gca().set_xlabel(
"Time [s]")
353 plt.gca().set_ylabel(
"Normalized Joint Vel")