demo_quadruped.py
Go to the documentation of this file.
1 import os
2 import subprocess
3 import sys
4 import time
5 from pathlib import Path
6 
7 import gepetto.corbaserver
8 import matplotlib.pyplot as plt
9 import numpy as np
10 import pinocchio as pin
11 import plot_utils as plut
12 import tsid
13 from numpy import nan
14 from numpy.linalg import norm as norm
15 
16 sys.path += [Path.cwd().parent / "exercizes"]
17 
18 np.set_printoptions(precision=3, linewidth=200, suppress=True)
19 
20 LINE_WIDTH = 60
21 print("".center(LINE_WIDTH, "#"))
22 print(" Test TSID with Quadruped Robot ".center(LINE_WIDTH, "#"))
23 print("".center(LINE_WIDTH, "#"), "\n")
24 
25 mu = 0.3 # friction coefficient
26 fMin = 1.0 # minimum normal force
27 fMax = 100.0 # maximum normal force
28 contact_frames = ["BL_contact", "BR_contact", "FL_contact", "FR_contact"]
29 contactNormal = np.array(
30  [0.0, 0.0, 1.0]
31 ) # direction of the normal to the contact surface
32 
33 w_com = 1.0 # weight of center of mass task
34 w_posture = 1e-3 # weight of joint posture task
35 w_forceRef = 1e-5 # weight of force regularization task
36 
37 kp_contact = 10.0 # proportional gain of contact constraint
38 kp_com = 10.0 # proportional gain of center of mass task
39 kp_posture = 10.0 # proportional gain of joint posture task
40 
41 dt = 0.001 # controller time step
42 PRINT_N = 500 # print every PRINT_N time steps
43 DISPLAY_N = 25 # update robot configuration in viwewer every DISPLAY_N time steps
44 N_SIMULATION = 6000 # number of time steps simulated
45 
46 filename = str(Path(__file__).resolve().parent)
47 path = filename + "/../models"
48 urdf = path + "/quadruped/urdf/quadruped.urdf"
49 vector = pin.StdVec_StdString()
50 vector.extend(item for item in path)
51 robot = tsid.RobotWrapper(urdf, vector, pin.JointModelFreeFlyer(), False)
52 
53 # for gepetto viewer
54 robot_display = pin.RobotWrapper.BuildFromURDF(
55  urdf,
56  [
57  path,
58  ],
59  pin.JointModelFreeFlyer(),
60 )
61 n = subprocess.getstatusoutput("ps aux |grep 'gepetto-gui'|grep -v 'grep'|wc -l")
62 if int(n[1]) == 0:
63  os.system("gepetto-gui &")
64 time.sleep(1)
65 cl = gepetto.corbaserver.Client()
66 gui = cl.gui
67 robot_display.initViewer(loadModel=True)
68 
69 # model = robot.model()
70 # pin.loadReferenceConfigurations(model, srdf, False)
71 # q = model.referenceConfigurations["half_sitting"]
72 # q = pin.getNeutralConfigurationFromSrdf(robot.model(), srdf, False)
73 # q = robot_display.model.neutralConfiguration #np.zeros(robot.nq)
74 q = np.zeros(robot.nq)
75 q[6] = 1.0
76 q[2] += 0.5
77 for i in range(4):
78  q[7 + 2 * i] = -0.8
79  q[8 + 2 * i] = 1.6
80 v = np.zeros(robot.nv)
81 
82 robot_display.displayCollisions(False)
83 robot_display.displayVisuals(True)
84 robot_display.display(q)
85 
86 assert [robot.model().existFrame(name) for name in contact_frames]
87 
88 t = 0.0 # time
89 invdyn = tsid.InverseDynamicsFormulationAccForce("tsid", robot, False)
90 invdyn.computeProblemData(t, q, v)
91 data = invdyn.data()
92 
93 # Place the robot onto the ground.
94 id_contact = robot_display.model.getFrameId(contact_frames[0])
95 q[2] -= robot.framePosition(data, id_contact).translation[2]
96 robot.computeAllTerms(data, q, v)
97 
98 contacts = 4 * [None]
99 for i, name in enumerate(contact_frames):
100  contacts[i] = tsid.ContactPoint(name, robot, name, contactNormal, mu, fMin, fMax)
101  contacts[i].setKp(kp_contact * np.ones(3))
102  contacts[i].setKd(2.0 * np.sqrt(kp_contact) * np.ones(3))
103  H_rf_ref = robot.framePosition(data, robot.model().getFrameId(name))
104  contacts[i].setReference(H_rf_ref)
105  contacts[i].useLocalFrame(False)
106  invdyn.addRigidContact(contacts[i], w_forceRef, 1.0, 1)
107 
108 comTask = tsid.TaskComEquality("task-com", robot)
109 comTask.setKp(kp_com * np.ones(3))
110 comTask.setKd(2.0 * np.sqrt(kp_com) * np.ones(3))
111 invdyn.addMotionTask(comTask, w_com, 1, 0.0)
112 
113 postureTask = tsid.TaskJointPosture("task-posture", robot)
114 postureTask.setKp(kp_posture * np.ones(robot.nv - 6))
115 postureTask.setKd(2.0 * np.sqrt(kp_posture) * np.ones(robot.nv - 6))
116 invdyn.addMotionTask(postureTask, w_posture, 1, 0.0)
117 
118 com_ref = robot.com(data)
119 trajCom = tsid.TrajectoryEuclidianConstant("traj_com", com_ref)
120 sampleCom = trajCom.computeNext()
121 
122 q_ref = q[7:]
123 trajPosture = tsid.TrajectoryEuclidianConstant("traj_joint", q_ref)
124 
125 print(
126  "Create QP solver with ",
127  invdyn.nVar,
128  " variables, ",
129  invdyn.nEq,
130  " equality and ",
131  invdyn.nIn,
132  " inequality constraints",
133 )
134 solver = tsid.SolverHQuadProgFast("qp solver")
135 solver.resize(invdyn.nVar, invdyn.nEq, invdyn.nIn)
136 
137 com_pos = np.empty((3, N_SIMULATION)) * nan
138 com_vel = np.empty((3, N_SIMULATION)) * nan
139 com_acc = np.empty((3, N_SIMULATION)) * nan
140 
141 com_pos_ref = np.empty((3, N_SIMULATION)) * nan
142 com_vel_ref = np.empty((3, N_SIMULATION)) * nan
143 com_acc_ref = np.empty((3, N_SIMULATION)) * nan
144 com_acc_des = (
145  np.empty((3, N_SIMULATION)) * nan
146 ) # acc_des = acc_ref - Kp*pos_err - Kd*vel_err
147 
148 offset = robot.com(data) + np.array([0.0, 0.0, 0.0])
149 amp = np.array([0.0, 0.03, 0.0])
150 two_pi_f = 2 * np.pi * np.array([0.0, 2.0, 0.7])
151 two_pi_f_amp = np.multiply(two_pi_f, amp)
152 two_pi_f_squared_amp = np.multiply(two_pi_f, two_pi_f_amp)
153 
154 for i in range(0, N_SIMULATION):
155  time_start = time.time()
156 
157  sampleCom.pos(offset + np.multiply(amp, np.sin(two_pi_f * t)))
158  sampleCom.vel(np.multiply(two_pi_f_amp, np.cos(two_pi_f * t)))
159  sampleCom.acc(np.multiply(two_pi_f_squared_amp, -np.sin(two_pi_f * t)))
160 
161  comTask.setReference(sampleCom)
162  samplePosture = trajPosture.computeNext()
163  postureTask.setReference(samplePosture)
164 
165  HQPData = invdyn.computeProblemData(t, q, v)
166  if i == 0:
167  HQPData.print_all()
168 
169  sol = solver.solve(HQPData)
170  if sol.status != 0:
171  print(f"[{i}] QP problem could not be solved! Error code", sol.status)
172  break
173 
174  tau = invdyn.getActuatorForces(sol)
175  dv = invdyn.getAccelerations(sol)
176 
177  com_pos[:, i] = robot.com(invdyn.data())
178  com_vel[:, i] = robot.com_vel(invdyn.data())
179  com_acc[:, i] = comTask.getAcceleration(dv)
180  com_pos_ref[:, i] = sampleCom.pos()
181  com_vel_ref[:, i] = sampleCom.vel()
182  com_acc_ref[:, i] = sampleCom.acc()
183  com_acc_des[:, i] = comTask.getDesiredAcceleration
184 
185  if i % PRINT_N == 0:
186  print(f"Time {t:.3f}")
187  print("\tNormal forces: ", end=" ")
188  for contact in contacts:
189  if invdyn.checkContact(contact.name, sol):
190  f = invdyn.getContactForce(contact.name, sol)
191  print(f"{contact.getNormalForce(f):4.1f}", end=" ")
192 
193  print(
194  "\n\ttracking err {}: {:.3f}".format(
195  comTask.name.ljust(20, "."), norm(comTask.position_error, 2)
196  )
197  )
198  print(f"\t||v||: {norm(v, 2):.3f}\t ||dv||: {norm(dv):.3f}")
199 
200  v_mean = v + 0.5 * dt * dv
201  v += dt * dv
202  q = pin.integrate(robot.model(), q, dt * v_mean)
203  t += dt
204 
205  if i % DISPLAY_N == 0:
206  robot_display.display(q)
207 
208  time_spent = time.time() - time_start
209  if time_spent < dt:
210  time.sleep(dt - time_spent)
211 
212 # PLOT STUFF
213 time = np.arange(0.0, N_SIMULATION * dt, dt)
214 
215 (f, ax) = plut.create_empty_figure(3, 1)
216 for i in range(3):
217  ax[i].plot(time, com_pos[i, :], label="CoM " + str(i))
218  ax[i].plot(time, com_pos_ref[i, :], "r:", label="CoM Ref " + str(i))
219  ax[i].set_xlabel("Time [s]")
220  ax[i].set_ylabel("CoM [m]")
221  leg = ax[i].legend()
222  leg.get_frame().set_alpha(0.5)
223 
224 (f, ax) = plut.create_empty_figure(3, 1)
225 for i in range(3):
226  ax[i].plot(time, com_vel[i, :], label="CoM Vel " + str(i))
227  ax[i].plot(time, 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]")
230  leg = ax[i].legend()
231  leg.get_frame().set_alpha(0.5)
232 
233 (f, ax) = plut.create_empty_figure(3, 1)
234 for i in range(3):
235  ax[i].plot(time, com_acc[i, :], label="CoM Acc " + str(i))
236  ax[i].plot(time, 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]")
240  leg = ax[i].legend()
241  leg.get_frame().set_alpha(0.5)
242 
243 plt.show()
plot
center
Vec3f center
tsid::InverseDynamicsFormulationAccForce
Definition: inverse-dynamics-formulation-acc-force.hpp:40


tsid
Author(s): Andrea Del Prete, Justin Carpentier
autogenerated on Sat May 3 2025 02:48:16