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 "Time %.3f Changing contact phase from %s to %s" 100 % (t, contact_phase[i - 1], contact_phase[i])
102 if contact_phase[i] ==
"left":
103 tsid.add_contact_LF()
104 tsid.remove_contact_RF()
106 tsid.add_contact_RF()
107 tsid.remove_contact_LF()
110 if contact_phase[i - 1] ==
"left":
111 tsid.add_contact_RF()
113 tsid.add_contact_LF()
117 com_pos_ref[:, 0], 0 * com_vel_ref[:, 0], 0 * com_acc_ref[:, 0]
120 tsid.set_com_ref(com_pos_ref[:, i], com_vel_ref[:, i], com_acc_ref[:, i])
121 tsid.set_LF_3d_ref(x_LF_ref[:, i], dx_LF_ref[:, i], ddx_LF_ref[:, i])
122 tsid.set_RF_3d_ref(x_RF_ref[:, i], dx_RF_ref[:, i], ddx_RF_ref[:, i])
123 tsid.copTask.setReference(np.concatenate([cop_ref[:, i], np.zeros(1)]))
125 HQPData = tsid.formulation.computeProblemData(t, q, v)
127 sol = tsid.solver.solve(HQPData)
129 print(
"QP problem could not be solved! Error code:", sol.status)
131 if norm(v, 2) > 40.0:
132 print(
"Time %.3f Velocities are too high, stop everything!" % (t), norm(v))
138 tau[:, i] = tsid.formulation.getActuatorForces(sol)
139 dv = tsid.formulation.getAccelerations(sol)
142 com_pos[:, i] = tsid.robot.com(tsid.formulation.data())
143 com_vel[:, i] = tsid.robot.com_vel(tsid.formulation.data())
144 com_acc[:, i] = tsid.comTask.getAcceleration(dv)
145 com_acc_des[:, i] = tsid.comTask.getDesiredAcceleration
146 x_LF[:, i], dx_LF[:, i], ddx_LF[:, i] = tsid.get_LF_3d_pos_vel_acc(dv)
147 if not tsid.contact_LF_active:
148 ddx_LF_des[:, i] = tsid.leftFootTask.getDesiredAcceleration[:3]
149 x_RF[:, i], dx_RF[:, i], ddx_RF[:, i] = tsid.get_RF_3d_pos_vel_acc(dv)
150 if not tsid.contact_RF_active:
151 ddx_RF_des[:, i] = tsid.rightFootTask.getDesiredAcceleration[:3]
153 if tsid.formulation.checkContact(tsid.contactRF.name, sol):
154 T_RF = tsid.contactRF.getForceGeneratorMatrix
155 f_RF[:, i] = T_RF.dot(
156 tsid.formulation.getContactForce(tsid.contactRF.name, sol)
158 if f_RF[2, i] > 1e-3:
159 cop_RF[0, i] = f_RF[4, i] / f_RF[2, i]
160 cop_RF[1, i] = -f_RF[3, i] / f_RF[2, i]
161 if tsid.formulation.checkContact(tsid.contactLF.name, sol):
162 T_LF = tsid.contactRF.getForceGeneratorMatrix
163 f_LF[:, i] = T_LF.dot(
164 tsid.formulation.getContactForce(tsid.contactLF.name, sol)
166 if f_LF[2, i] > 1e-3:
167 cop_LF[0, i] = f_LF[4, i] / f_LF[2, i]
168 cop_LF[1, i] = -f_LF[3, i] / f_LF[2, i]
169 cop_LF_world = tsid.get_placement_LF().act(
170 np.array([cop_LF[0, i], cop_LF[1, i], 0])
172 cop_RF_world = tsid.get_placement_RF().act(
173 np.array([cop_RF[0, i], cop_RF[1, i], 0])
175 cop[:, i] = (cop_LF_world[:2] * f_LF[2, i] + cop_RF_world[:2] * f_RF[2, i]) / (
176 f_LF[2, i] + f_RF[2, i]
179 if i % conf.PRINT_N == 0:
180 print(
"Time %.3f" % (t))
181 if tsid.formulation.checkContact(tsid.contactRF.name, sol)
and i >= 0:
183 "\tnormal force %s: %.1f" 184 % (tsid.contactRF.name.ljust(20,
"."), f_RF[2, i])
187 if tsid.formulation.checkContact(tsid.contactLF.name, sol)
and i >= 0:
189 "\tnormal force %s: %.1f" 190 % (tsid.contactLF.name.ljust(20,
"."), f_LF[2, i])
194 "\ttracking err %s: %.3f" 195 % (tsid.comTask.name.ljust(20,
"."), norm(tsid.comTask.position_error, 2))
197 print(
"\t||v||: %.3f\t ||dv||: %.3f" % (norm(v, 2), norm(dv)))
199 q, v = tsid.integrate_dv(q, v, dv, conf.dt)
202 if i % conf.DISPLAY_N == 0:
205 time_spent = time.time() - time_start
206 if time_spent < conf.dt:
207 time.sleep(conf.dt - time_spent)
210 time = np.arange(0.0, (N + N_post) * conf.dt, conf.dt)
213 (f, ax) = plut.create_empty_figure(3, 1)
215 ax[i].plot(time, com_pos[i, :], label=
"CoM " + str(i))
216 ax[i].plot(time[:N], com_pos_ref[i, :],
"r:", label=
"CoM Ref " + str(i))
217 ax[i].set_xlabel(
"Time [s]")
218 ax[i].set_ylabel(
"CoM [m]")
220 leg.get_frame().set_alpha(0.5)
222 (f, ax) = plut.create_empty_figure(3, 1)
224 ax[i].plot(time, com_vel[i, :], label=
"CoM Vel " + str(i))
225 ax[i].plot(time[:N], com_vel_ref[i, :],
"r:", label=
"CoM Vel Ref " + str(i))
226 ax[i].set_xlabel(
"Time [s]")
227 ax[i].set_ylabel(
"CoM Vel [m/s]")
229 leg.get_frame().set_alpha(0.5)
231 (f, ax) = plut.create_empty_figure(3, 1)
233 ax[i].plot(time, com_acc[i, :], label=
"CoM Acc " + str(i))
234 ax[i].plot(time[:N], com_acc_ref[i, :],
"r:", label=
"CoM Acc Ref " + str(i))
235 ax[i].plot(time, com_acc_des[i, :],
"g--", label=
"CoM Acc Des " + str(i))
236 ax[i].set_xlabel(
"Time [s]")
237 ax[i].set_ylabel(
"CoM Acc [m/s^2]")
239 leg.get_frame().set_alpha(0.5)
242 (f, ax) = plut.create_empty_figure(2, 1)
244 ax[i].plot(time, cop_LF[i, :], label=
"CoP LF " + str(i))
245 ax[i].plot(time, cop_RF[i, :], label=
"CoP RF " + str(i))
249 [-conf.lxn, -conf.lxn],
251 label=
"CoP Lim " + str(i),
255 [conf.lxp, conf.lxp],
257 label=
"CoP Lim " + str(i),
262 [-conf.lyn, -conf.lyn],
264 label=
"CoP Lim " + str(i),
268 [conf.lyp, conf.lyp],
270 label=
"CoP Lim " + str(i),
272 ax[i].set_xlabel(
"Time [s]")
273 ax[i].set_ylabel(
"CoP (local) [m]")
275 leg.get_frame().set_alpha(0.5)
277 (f, ax) = plut.create_empty_figure(2, 1)
279 ax[i].plot(time[:N], cop_ref[i, :], label=
"CoP ref " + str(i))
280 ax[i].plot(time, cop[i, :], label=
"CoP " + str(i))
281 ax[i].set_xlabel(
"Time [s]")
282 ax[i].set_ylabel(
"CoP (world) [m]")
284 leg.get_frame().set_alpha(0.5)
299 plt.plot(time, x_RF[i, :], label=
"x RF " + str(i))
300 plt.plot(time[:N], x_RF_ref[i, :],
":", label=
"x RF ref " + str(i))
301 plt.plot(time, x_LF[i, :], label=
"x LF " + str(i))
302 plt.plot(time[:N], x_LF_ref[i, :],
":", label=
"x LF ref " + str(i))
325 for i
in range(tsid.robot.na):
327 2 * (tau[i, :] - tsid.tau_min[i]) / (tsid.tau_max[i] - tsid.tau_min[i]) - 1
330 if np.max(np.abs(tau_normalized)) > 0.5:
331 plt.plot(time, tau_normalized, alpha=0.5, label=tsid.model.names[i + 2])
332 plt.plot([time[0], time[-1]], 2 * [-1.0],
":")
333 plt.plot([time[0], time[-1]], 2 * [1.0],
":")
334 plt.gca().set_xlabel(
"Time [s]")
335 plt.gca().set_ylabel(
"Normalized Torque")
337 leg.get_frame().set_alpha(0.5)
341 for i
in range(tsid.robot.na):
343 2 * (v_log[6 + i, :] - tsid.v_min[i]) / (tsid.v_max[i] - tsid.v_min[i]) - 1
346 if np.max(np.abs(v_normalized)) > 0.5:
347 plt.plot(time, v_normalized, alpha=0.5, label=tsid.model.names[i + 2])
348 plt.plot([time[0], time[-1]], 2 * [-1.0],
":")
349 plt.plot([time[0], time[-1]], 2 * [1.0],
":")
350 plt.gca().set_xlabel(
"Time [s]")
351 plt.gca().set_ylabel(
"Normalized Joint Vel")