Skip to content

Commit 331e58a

Browse files
committed
CPG controller based on 4 Hopf Oscillators
1 parent 02ee846 commit 331e58a

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

mathematics/cpg/code.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
###
2+
# CPG controller based on 4 Hopf Oscillators
3+
#
4+
# Params:
5+
# alpha: Rate of convergence
6+
# mu: control the amplitude of the output signals, A = sqrt(mu)
7+
# beta: Duty cycle of the support phase (Load Factor)
8+
# omega_st / omega_sw = (1 - beta) / beta
9+
# omega_sw: Frequency of the swing phase
10+
# omega_st: Frequency of the support phase
11+
# a: rate of the change between omega_sw and omega_st
12+
# u: (optional, default 0), feedback, EX: u1 <=> x1, u2<=> y2...
13+
#
14+
# Outputs:
15+
# x1, y1 => LF
16+
# x2, y2 => RF
17+
# x3, y3 => LH
18+
# x4, y4 => RH
19+
###
20+
21+
import matplotlib.pyplot as plt
22+
import numpy as np
23+
24+
alpha = 100
25+
beta = 0.75
26+
mu = 1
27+
omega_sw = 5 * np.pi
28+
omega_st = omega_sw * (1 - beta) / beta
29+
a = 100
30+
31+
# phase config of walk gait
32+
phi_LF = 0
33+
phi_RF = 0.5
34+
phi_LH = 0.75
35+
phi_RH = 0.25
36+
# phase order
37+
phi = [phi_LF, phi_RF, phi_LH, phi_RH]
38+
39+
# 5 seconds
40+
sim_duration = 5
41+
dt = 0.01
42+
iteration = 10
43+
44+
x1, y1, x2, y2, x3, y3, x4, y4 = np.random.uniform(0, 1, 8)
45+
Q = np.matrix([x1, y1, x2, y2, x3, y3, x4, y4]).T
46+
47+
# result collection
48+
x1_t = []
49+
y1_t = []
50+
x2_t = []
51+
y2_t = []
52+
x3_t = []
53+
y3_t = []
54+
x4_t = []
55+
y4_t = []
56+
t_t = np.arange(0, sim_duration, dt)
57+
58+
for t in t_t:
59+
for _ in np.arange(iteration):
60+
r1_square = x1 ** 2 + y1 ** 2
61+
r2_square = x2 ** 2 + y2 ** 2
62+
r3_square = x3 ** 2 + y3 ** 2
63+
r4_square = x4 ** 2 + y4 ** 2
64+
65+
# Frequency of the Oscillator
66+
omega1 = omega_st / (np.exp(- a * y1) + 1) + omega_sw / (np.exp(a * y1) + 1)
67+
omega2 = omega_st / (np.exp(- a * y2) + 1) + omega_sw / (np.exp(a * y2) + 1)
68+
omega3 = omega_st / (np.exp(- a * y3) + 1) + omega_sw / (np.exp(a * y3) + 1)
69+
omega4 = omega_st / (np.exp(- a * y4) + 1) + omega_sw / (np.exp(a * y4) + 1)
70+
71+
FQ = np.matrix([
72+
alpha * (mu - r1_square) * x1 - omega1 * y1,
73+
alpha * (mu - r1_square) * y1 + omega1 * x1,
74+
alpha * (mu - r2_square) * x2 - omega2 * y2,
75+
alpha * (mu - r2_square) * y2 + omega2 * x2,
76+
alpha * (mu - r3_square) * x3 - omega3 * y3,
77+
alpha * (mu - r3_square) * y3 + omega3 * x3,
78+
alpha * (mu - r4_square) * x4 - omega4 * y4,
79+
alpha * (mu - r4_square) * y4 + omega4 * x4
80+
]).T
81+
82+
"""
83+
R = [
84+
R11, R21, R31, R41;
85+
R12, R22, R32, R42;
86+
R13, R23, R33, R43;
87+
R14, R24, R34, R44
88+
]
89+
90+
Rji = [
91+
cos(theta_ji), -sin(theta_ji);
92+
sin(theta_ji), cos(theta_ji)
93+
]
94+
95+
theta_ji = phi_j - phi_i
96+
"""
97+
R = np.asmatrix(np.full((8, 8), None))
98+
for i in range(0, 4):
99+
for j in range(0, 4):
100+
theta_ji = 2 * np.pi * (phi[i] - phi[j])
101+
R[i * 2, j * 2] = np.cos(theta_ji)
102+
R[i * 2, j * 2 + 1] = - np.sin(theta_ji)
103+
R[i * 2 + 1, j * 2] = np.sin(theta_ji)
104+
R[i * 2 + 1, j * 2 + 1] = R[i * 2, j * 2]
105+
106+
# Q_dot = F(Q) + RQ
107+
Q_dot = FQ + np.dot(R, Q)
108+
109+
Q = Q + Q_dot * dt / iteration
110+
x1 = Q[0, 0]
111+
y1 = Q[1, 0]
112+
x2 = Q[2, 0]
113+
y2 = Q[3, 0]
114+
x3 = Q[4, 0]
115+
y3 = Q[5, 0]
116+
x4 = Q[6, 0]
117+
y4 = Q[7, 0]
118+
119+
x1_t.append(x1)
120+
y1_t.append(y1)
121+
x2_t.append(x2)
122+
y2_t.append(y2)
123+
x3_t.append(x3)
124+
y3_t.append(y3)
125+
x4_t.append(x4)
126+
y4_t.append(y4)
127+
128+
fig, (ax0, ax1, ax2, ax3) = plt.subplots(4, 1)
129+
ax0.plot(t_t, x1_t, label='hip')
130+
plt.ylabel('LF')
131+
ax1.plot(t_t, x2_t, label='hip')
132+
plt.ylabel('RF')
133+
ax2.plot(t_t, x3_t, label='hip')
134+
plt.ylabel('LH')
135+
ax3.plot(t_t, x4_t, label='hip')
136+
plt.ylabel('RH')
137+
138+
plt.legend()
139+
140+
141+
plt.show()

0 commit comments

Comments
 (0)