Skip to content

Commit 2c41dfe

Browse files
committed
Finished ADRC and added Readme
1 parent a448d3d commit 2c41dfe

18 files changed

+104
-41
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# TSwR Student - Laboratory
2+
3+
Miniprojects from the course "Control Theory in Robotics" during my 1st semester of the Master's.
4+
5+
## List of implemented algorithms:
6+
7+
1. [Feedback Linearization Controller](/controllers/feedback_linearization.py)
8+
2. [Multi-model Adaptive Controller](/controllers/mma_controller.py)
9+
3. [PD Controller](/controllers/pd_controller.py)
10+
4. [Active Disturbance Rejection Controller](/controllers/adrc_joint_controller.py)
11+
5. [Active Disturbance Rejection Controller with Feedback Linearization](/controllers/adrc_flc_controller.py)
12+
13+
## List of implemented modules:
14+
15+
1. [Extended State Observer](/observers/eso.py)
16+
2. [Polynomial Trajectory Generator](/trajectory_generators/poly3.py)
17+
3. [Robot Model](/models/manipulator_model.py)
18+
19+
# Final result:
20+
21+
![Final result for sinusoidal trajectory](/pictures/TSwR.gif)

adrc.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
traj_gen = Sinusoidal(np.array([0., 1.]), np.array([2., 2.]), np.array([0., 0.]))
1818
# traj_gen = Poly3(np.array([0., 0.]), np.array([pi/4, pi/6]), end)
1919

20-
b_est_1 = None
21-
b_est_2 = None
22-
kp_est_1 = None
23-
kp_est_2 = None
24-
kd_est_1 = None
25-
kd_est_2 = None
26-
p1 = None
27-
p2 = None
20+
b_est_1 = 2
21+
b_est_2 = 10
22+
kp_est_1 = 100
23+
kp_est_2 = 20
24+
kd_est_1 = 50
25+
kd_est_2 = 10
26+
p1 = 100
27+
p2 = 100
2828

2929
q0, qdot0, _ = traj_gen.generate(0.)
3030
q1_0 = np.array([q0[0], qdot0[0]])

adrflc.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@
77
from utils.simulation import simulate
88

99
Tp = 0.001
10-
end = 5
10+
end = 30
1111

1212
# traj_gen = ConstantTorque(np.array([0., 1.0])[:, np.newaxis])
1313
traj_gen = Sinusoidal(np.array([0., 1.]), np.array([2., 2.]), np.array([0., 0.]))
1414
# traj_gen = Poly3(np.array([0., 0.]), np.array([pi/4, pi/6]), end)
1515

16-
b_est_1 = None
17-
b_est_2 = None
18-
kp_est_1 = None
19-
kp_est_2 = None
20-
kd_est_1 = None
21-
kd_est_2 = None
22-
p1 = None
23-
p2 = None
16+
b_est_1 = 2
17+
b_est_2 = 10
18+
kp_est_1 = 100
19+
kp_est_2 = 20
20+
kd_est_1 = 50
21+
kd_est_2 = 10
22+
p1 = 100
23+
p2 = 100
2424

2525
q0, qdot0, _ = traj_gen.generate(0.)
2626
q1_0 = np.array([q0[0], qdot0[0]])
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

controllers/adrc_controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def __init__(self, Tp, params):
1212
def calculate_control(self, x, q_d, q_d_dot, q_d_ddot):
1313
u = []
1414
for i, controller in enumerate(self.joint_controllers):
15-
u.append(controller.calculate_control([x[i], x[i+2]], q_d[i], q_d_dot[i], q_d_ddot[i]))
15+
u.append(controller.calculate_control(x, q_d[i], q_d_dot[i], q_d_ddot[i], i))
1616
u = np.array(u)[:, np.newaxis]
1717
return u
1818

controllers/adrc_flc_controller.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,49 @@
11
import numpy as np
22

3-
from models.free_model import FreeModel
3+
#from models.free_model import FreeModel
44
from observers.eso import ESO
55
from .adrc_joint_controller import ADRCJointController
66
from .controller import Controller
7-
from models.ideal_model import IdealModel
7+
#from models.ideal_model import IdealModel
8+
from models.manipulator_model import ManiuplatorModel
89

910

1011
class ADRFLController(Controller):
1112
def __init__(self, Tp, q0, Kp, Kd, p):
12-
self.model = None
13+
self.model = ManiuplatorModel(Tp)
1314
self.Kp = Kp
1415
self.Kd = Kd
15-
self.L = None
16-
W = None
17-
A = None
18-
B = None
19-
self.eso = ESO(A, B, W, self.L, q0, Tp)
16+
self.L = np.array([[3*p[0], 0], [0, 3*p[1]], [3*p[0]**2, 0], [0, 3*p[1]**2], [p[0]**3, 0], [0, p[1]**3]])
17+
W = np.array([[1., 0., 0., 0., 0., 0.], [0., 1., 0., 0., 0., 0.]])
18+
self.A = np.array([[0., 0., 1., 0., 0., 0.], [0., 0., 0., 1., 0., 0.], [0., 0., 0., 0., 1., 0.],
19+
[0., 0., 0., 0., 0., 1.], [0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0.]])
20+
self.B = np.zeros((6, 2))
21+
self.eso = ESO(self.A, self.B, W, self.L, q0, Tp)
2022
self.update_params(q0[:2], q0[2:])
2123

2224
def update_params(self, q, q_dot):
2325
### TODO Implement procedure to set eso.A and eso.B
24-
self.eso.A = None
25-
self.eso.B = None
26+
x = np.concatenate([q, q_dot])
27+
inv_M = np.linalg.inv(self.model.M(x.flatten()))
28+
inv_M_C = inv_M @ self.model.C(x.flatten())
29+
self.A[2:4, 2:4] = - inv_M_C
30+
self.B[2:4, :] = inv_M
31+
self.eso.A = self.A
32+
self.eso.B = self.B
2633

2734
def calculate_control(self, x, q_d, q_d_dot, q_d_ddot):
2835
### TODO implement centralized ADRFLC
29-
return NotImplementedError
36+
z = self.eso.get_state()
37+
z = z[:, np.newaxis]
38+
v = q_d_ddot - self.Kp @ (x[:2] - q_d) - self.Kd @ (x[2:] - q_d_dot)
39+
# print(v.shape)
40+
# print(z[:4].shape)
41+
# print(z[4:].shape)
42+
# print(z[2:4].shape)
43+
# print(x.shape)
44+
#u = self.model.M(z[0:4]) @ (v[:, np.newaxis] - z[4:]) + self.model.C(z[0:4]) @ z[2:4]
45+
u = self.model.M(z[0:4].flatten()) @ (v[:, np.newaxis] - z[4:]) + self.model.C(z[0:4].flatten()) @ z[2:4]
46+
self.update_params(z[0:2], z[2:4])
47+
self.eso.update(x[:2], u)
48+
return u
49+
#return NotImplementedError

controllers/adrc_joint_controller.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,43 @@
11
import numpy as np
22
from observers.eso import ESO
33
from .controller import Controller
4+
from models.manipulator_model import ManiuplatorModel
45

56

67
class ADRCJointController(Controller):
78
def __init__(self, b, kp, kd, p, q0, Tp):
89
self.b = b
910
self.kp = kp
1011
self.kd = kd
12+
self.model = ManiuplatorModel(Tp)
1113

12-
A = None
13-
B = None
14-
L = None
15-
W = None
14+
A = np.array([[0., 1., 0.], [0., 0., 1.], [0., 0., 0.]])
15+
B = np.array([[0.], [self.b], [0.]])
16+
L = np.array([[3*p], [3*p**2], [p**3]])
17+
W = np.array([1., 0., 0.])
1618
self.eso = ESO(A, B, W, L, q0, Tp)
19+
self.prev_u = 0.
1720

1821
def set_b(self, b):
1922
### TODO update self.b and B in ESO
20-
return NotImplementedError
23+
self.b = b
24+
B = np.array([[0.], [self.b], [0.]])
25+
self.eso.set_B(B)
2126

22-
def calculate_control(self, x, q_d, q_d_dot, q_d_ddot):
27+
def calculate_control(self, x, q_d, q_d_dot, q_d_ddot, i):
2328
### TODO implement ADRC
24-
return NotImplementedError
29+
30+
u_arr = np.array([self.prev_u])
31+
self.eso.update(x[i], u_arr[:, np.newaxis])
32+
z = self.eso.get_state()
33+
print("controller")
34+
print(z)
35+
q, q_dot, f = z
36+
v = q_d_ddot + self.kd * (q_d_dot - q_dot) + self.kp * (q_d - q)
37+
u = (v - f) / self.b
38+
self.prev_u = u
39+
40+
B = np.linalg.inv(self.model.M(x))
41+
self.set_b(B[i, i])
42+
43+
return u

controllers/pd_controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ def __init__(self, kp, kd):
99

1010
def calculate_control(self, q, q_dot, q_d, q_d_dot, q_d_ddot):
1111
### TODO: Please implement me
12-
u = None
12+
u = self.kp * (q_d - q) + self.kd * (q_d_dot - q_dot)
1313
return u

flc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
Tp = 0.01
1212
start = 0
13-
end = 3
13+
end = 30
1414

1515
"""
1616
Switch to FeedbackLinearizationController as soon as you implement it
@@ -23,8 +23,8 @@
2323
At the end implement Point2point trajectory generator to move your manipulator to some desired state.
2424
"""
2525
#traj_gen = ConstantTorque(np.array([0., 1.0])[:, np.newaxis])
26-
# traj_gen = Sinusoidal(np.array([0., 1.]), np.array([2., 2.]), np.array([0., 0.]))
27-
traj_gen = Poly3(np.array([0., 0.]), np.array([np.pi/4, np.pi/6]), end)
26+
traj_gen = Sinusoidal(np.array([0., 1.]), np.array([2., 2.]), np.array([0., 0.]))
27+
# traj_gen = Poly3(np.array([0., 0.]), np.array([np.pi/4, np.pi/6]), end)
2828

2929

3030
Q, Q_d, u, T = simulate("PYBULLET", traj_gen, controller, Tp, end)
Binary file not shown.

models/manipulator_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def __init__(self, Tp, m3=0.1, r3=0.05):
2121
self.gamma = self.m2*(self.l2/2)**2 + self.I_2 + self.m3 * self.l2**2 + self.I_3
2222

2323
self.Kp = np.array([[15, 0], [0, 15]])
24-
self.Kd = np.array([[30, 0], [0, 10]])
24+
self.Kd = np.array([[10, 0], [0, 10]])
2525

2626
def M(self, x):
2727
"""
157 Bytes
Binary file not shown.
1.2 KB
Binary file not shown.

observers/eso.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ def set_B(self, B):
1818
def update(self, q, u):
1919
self.states.append(copy(self.state))
2020
### TODO implement ESO update
21+
z_hat = self.state[:, np.newaxis]
22+
z_hat_dot = self.A @ z_hat + self.B @ u + np.array(self.L @ (q.reshape(-1, 1) - self.W @ z_hat))
23+
self.state = (z_hat + z_hat_dot * self.Tp).flatten()
2124

2225
def get_state(self):
2326
return self.state

pictures/TSwR.gif

222 KB
Loading

0 commit comments

Comments
 (0)