@@ -15,6 +15,33 @@ mutable struct LQR{T,N,NK} <: Controller
15
15
control!:: Function
16
16
17
17
18
+ function LQR (A, Bu, Bλ, G, Q, R, horizon, eqcids, xd, vd, qd, ωd, Fτd, Δt, :: Type{T} ) where {T}
19
+ Q = cat (Q... ,dims= (1 ,2 ))
20
+ R = cat (R... ,dims= (1 ,2 ))
21
+
22
+ N = horizon/ Δt
23
+ if N< Inf
24
+ N = Integer (ceil (horizon/ Δt))
25
+ Ntemp = N
26
+ else
27
+ Ntemp = Integer (ceil (10 / Δt)) # 10 second time horizon as maximal horizon for convergence for Inf
28
+ end
29
+
30
+ # calculate K
31
+ if size (G)[1 ] == 0
32
+ @assert size (Bλ)[2 ] == 0
33
+ Ku = dlqr (A, Bu, Q, R, N) # can be calculated directly
34
+ else
35
+ Ku = dlqr (A, Bu, Bλ, G, Q, R, Ntemp)
36
+ if N == Inf
37
+ Ku[1 ] != Ku[2 ] && @info " Riccati recursion did not converge."
38
+ Ku = [Ku[1 ]]
39
+ end
40
+ end
41
+
42
+ new {T, N, size(Ku[1][1])[2]} (Ku, xd, vd, qd, ωd, eqcids, Fτd, control_lqr!)
43
+ end
44
+
18
45
function LQR (mechanism:: Mechanism{T,Nn,Nb} , bodyids:: AbstractVector{<:Integer} , eqcids:: AbstractVector{<:Integer} ,
19
46
Q:: Vector{<:AbstractMatrix{T}} , R:: Vector{<:AbstractMatrix{T}} , horizon;
20
47
xd:: Vector{<:AbstractVector{T}} = [SA{T}[0 ; 0 ; 0 ] for i= 1 : Nb],
@@ -27,28 +54,10 @@ mutable struct LQR{T,N,NK} <: Controller
27
54
@assert length (bodyids) == length (Q) == length (xd) == length (vd) == length (qd) == length (ωd) == Nb " Missmatched length for bodies"
28
55
@assert length (eqcids) == length (R) == length (Fτd) " Missmatched length for constraints"
29
56
30
- Δt = mechanism. Δt
31
-
32
- N = horizon/ Δt
33
- if N< Inf
34
- N = Integer (ceil (horizon/ Δt))
35
- end
36
-
37
57
# linearize
38
58
A, Bu, Bλ, G = linearsystem (mechanism, xd, vd, qd, ωd, Fτd, bodyids, eqcids)
39
59
40
- Q = cat (Q... ,dims= (1 ,2 ))
41
- R = cat (R... ,dims= (1 ,2 ))
42
-
43
- # calculate K
44
- if size (G)[1 ] == 0
45
- @assert size (Bλ)[2 ] == 0
46
- Ku = dlqr (A, Bu, Q, R, N)
47
- else
48
- Ku = dlqr (A, Bu, Bλ, G, Q, R, N)
49
- end
50
-
51
- new {T, N, size(Ku[1][1])[2]} (Ku, xd, vd, qd, ωd, eqcids, Fτd, control_lqr!)
60
+ LQR (A, Bu, Bλ, G, Q, R, horizon, eqcids, xd, vd, qd, ωd, Fτd, mechanism. Δt, T)
52
61
end
53
62
54
63
function LQR (mechanism:: Mechanism{T,Nn,Nb} , controlledids:: AbstractVector{<:Integer} , controlids:: AbstractVector{<:Integer} ,
@@ -61,35 +70,19 @@ mutable struct LQR{T,N,NK} <: Controller
61
70
@assert length (controlledids) == length (Q) == length (xθd) == length (vωd) == Nb " Missmatched length for bodies"
62
71
@assert length (controlids) == length (R) == length (Fτd) " Missmatched length for constraints"
63
72
64
- Δt = mechanism. Δt
65
-
66
- N = horizon/ Δt
67
- if N< Inf
68
- N = Integer (ceil (horizon/ Δt))
69
- end
70
-
71
73
# linearize
72
74
A, Bu, Bλ, G, xd, vd, qd, ωd = linearsystem (mechanism, xθd, vωd, Fτd, controlledids, controlids)
73
75
74
76
Q = [diagm (ones (12 ))* Q[i] for i= 1 : length (Q)]
75
77
R = [diagm (ones (1 ))* R[i] for i= 1 : length (R)]
76
- Q = cat (Q... ,dims= (1 ,2 ))
77
- R = cat (R... ,dims= (1 ,2 ))
78
78
79
- # calculate K
80
- if size (G)[1 ] == 0
81
- @assert size (Bλ)[2 ] == 0
82
- Ku = dlqr (A, Bu, Q, R, N)
83
- else
84
- Ku = dlqr (A, Bu, Bλ, G, Q, R, N)
85
- end
86
-
87
- new {T, N, size(Ku[1][1])[2]} (Ku, xd, vd, qd, ωd, controlids, [[Fτd[i]] for i= 1 : length (Fτd)], control_lqr!)
79
+ LQR (A, Bu, Bλ, G, Q, R, horizon, controlids, xd, vd, qd, ωd, [[Fτd[i]] for i= 1 : length (Fτd)], mechanism. Δt, T)
88
80
end
89
81
end
90
82
91
83
function control_lqr! (mechanism:: Mechanism{T,Nn,Nb} , lqr:: LQR{T,N} , k) where {T,Nn,Nb,N}
92
84
Δz = zeros (T,Nb* 12 )
85
+ qvm = QuatVecMap ()
93
86
for (id,body) in pairs (mechanism. bodies)
94
87
colx = (id- 1 )* 12 + 1 : (id- 1 )* 12 + 3
95
88
colv = (id- 1 )* 12 + 4 : (id- 1 )* 12 + 6
@@ -99,7 +92,8 @@ function control_lqr!(mechanism::Mechanism{T,Nn,Nb}, lqr::LQR{T,N}, k) where {T,
99
92
state = body. state
100
93
Δz[colx] = state. xsol[2 ]- lqr. xd[id]
101
94
Δz[colv] = state. vsol[2 ]- lqr. vd[id]
102
- Δz[colq] = ConstrainedDynamics. VLᵀmat (lqr. qd[id]) * Rotations. params (state. qsol[2 ])
95
+ # Δz[colq] = ConstrainedDynamics.VLᵀmat(lqr.qd[id]) * Rotations.params(state.qsol[2])
96
+ Δz[colq] = rotation_error (state. qsol[2 ],lqr. qd[id],qvm)
103
97
Δz[colω] = state. ωsol[2 ]- lqr. ωd[id]
104
98
end
105
99
115
109
116
110
function control_lqr! (mechanism:: Mechanism{T,Nn,Nb} , lqr:: LQR{T,Inf} , k) where {T,Nn,Nb}
117
111
Δz = zeros (T,Nb* 12 )
112
+ qvm = QuatVecMap ()
118
113
for (id,body) in pairs (mechanism. bodies)
119
114
colx = (id- 1 )* 12 + 1 : (id- 1 )* 12 + 3
120
115
colv = (id- 1 )* 12 + 4 : (id- 1 )* 12 + 6
@@ -124,7 +119,7 @@ function control_lqr!(mechanism::Mechanism{T,Nn,Nb}, lqr::LQR{T,Inf}, k) where {
124
119
state = body. state
125
120
Δz[colx] = state. xsol[2 ]- lqr. xd[id]
126
121
Δz[colv] = state. vsol[2 ]- lqr. vd[id]
127
- Δz[colq] = ConstrainedDynamics . VLᵀmat (lqr . qd[id]) * Rotations . params ( state. qsol[2 ])
122
+ Δz[colq] = rotation_error ( state. qsol[2 ],lqr . qd[id],qvm )
128
123
Δz[colω] = state. ωsol[2 ]- lqr. ωd[id]
129
124
end
130
125
@@ -147,12 +142,6 @@ function dlqr(A,B,Q,R,N)
147
142
end
148
143
149
144
function dlqr (A,Bu,Bλ,G,Q,R,N)
150
- infflag = false
151
- if N == Inf
152
- infflag = true
153
- N = 1000
154
- end
155
-
156
145
mx = size (A)[2 ]
157
146
mu = size (Bu)[2 ]
158
147
mλ = size (Bλ)[2 ]
@@ -182,19 +171,15 @@ function dlqr(A,Bu,Bλ,G,Q,R,N)
182
171
Abar = A- Bu* Kuk- Bλ* Kλk
183
172
Pkp1 = Q + Kuk' * R* Kuk + Abar' * Pk* Abar
184
173
185
- if infflag && norm (Pk- Pkp1) < 1e-5
174
+ if norm (Pk- Pkp1) < 1e-5
186
175
break
187
176
end
188
177
189
178
Pk = Pkp1
190
179
end
191
180
192
- if infflag
193
- if k== 1
194
- @info " Riccati recursion did not converge."
195
- else
196
- Ku = [Ku[k]]
197
- end
181
+ for k2= k- 1 : - 1 : 1
182
+ Ku[k2] = Ku[k2+ 1 ]
198
183
end
199
184
200
185
return Ku
0 commit comments