Skip to content

Commit e2d72bd

Browse files
authored
Merge pull request #1011 from JuliaControl/realplace
make place return real matrix when expected
2 parents 479c1e7 + 7374520 commit e2d72bd

File tree

3 files changed

+29
-14
lines changed

3 files changed

+29
-14
lines changed

docs/src/examples/example.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,33 +74,33 @@ using LinearAlgebra
7474
using Plots
7575
7676
# Create system - same as LQR example
77-
Ts = 0.1
78-
A = [1 Ts; 0 1]
79-
B = [0; 1]
80-
C = I(2)
81-
P = ss(A,B,C,0,Ts)
77+
Ts = 0.1
78+
A = [1 Ts; 0 1]
79+
B = [0; 1]
80+
C = I(2)
81+
P = ss(A,B,C,0,Ts)
8282
8383
# Design controller using pole placement
8484
# Choose desired closed-loop poles (well-damped, faster than original system)
85-
desired_poles_cont = [-2+0.5im, -2-0.5im] # Continuous-time poles
86-
desired_poles = exp.(Ts .* desired_poles_cont) # Discrete-time poles inside unit circle
85+
desired_poles_cont = [-2+0.5im, -2-0.5im] # Continuous-time poles
86+
desired_poles = exp.(Ts .* desired_poles_cont) # Discrete-time poles
8787
8888
# Design state feedback gain using pole placement
89-
L = place(P, desired_poles) |> real
89+
L = place(P, desired_poles)
9090
91-
# Design observer with poles 5x faster (closer to origin for discrete time)
91+
# Design observer with poles 5x faster
9292
observer_poles = exp.(Ts*5 .* desired_poles_cont)
93-
K = place(P, observer_poles, :o) |> real # Note the :o for observer design
93+
K = place(P, observer_poles, :o) # Note the :o for observer design
9494
95-
# Create observer-controller using the observer_controller function
95+
# Create controller system
9696
controller = observer_controller(P, L, K)
9797
9898
# Form closed-loop system and analyze
9999
T_cl = feedback(P * controller)
100100
101101
r(x,t) = [1.5(t>=2.5); 0] # Form control law (r is a function of t and x), change reference to 1.5 at t≧2.5
102-
t = 0:Ts:5 # Time vector
103-
x0 = [1, 0, 0, 0] # Initial condition
102+
t = 0:Ts:5 # Time vector
103+
x0 = [1.0, 0, 0, 0] # Initial condition (plant state followed by controller state)
104104
res = lsim(T_cl, r, t; x0)
105105
plot(res, lab=["Position" "Velocity"], layout=1, sp=1)
106106
```

lib/ControlSystemsBase/src/synthesis.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ Please note that this function can be numerically sensitive, solving the placeme
150150
function place(A, B, p, opt=:c; direct = false, kwargs...)
151151
n = length(p)
152152
n != size(A,1) && error("Must specify as many poles as the state dimension")
153-
if opt === :c
153+
L = if opt === :c
154154
direct && error("direct = true only applies to observer design")
155155
n != size(B,1) && error("A and B must have same number of rows")
156156
if size(B,2) == 1
@@ -172,6 +172,11 @@ function place(A, B, p, opt=:c; direct = false, kwargs...)
172172
else
173173
error("fourth argument must be :c or :o")
174174
end
175+
if isreal(A) && isreal(B) && is_self_conjugate(p)
176+
@assert all(abs(imag(l)) .< 1e-6 for l in L) "Expected real coefficient in feedback gain, got complex: $L"
177+
return real(L)
178+
end
179+
return L
175180
end
176181
function place(sys::AbstractStateSpace, p, opt=:c; direct = false, kwargs...)
177182
if opt === :c

lib/ControlSystemsBase/src/types/SisoTfTypes/SisoZpk.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ function pairup_conjugates!(x::AbstractVector)
129129
end
130130
return true
131131
end
132+
function is_self_conjugate(x::AbstractVector)
133+
length(x) == 0 && return true # Empty vector is self-conjugate
134+
# Check that all complex numbers have a conjugate in the vector
135+
for i = eachindex(x)
136+
if findfirst((conj(x[i])), x) === nothing
137+
return false
138+
end
139+
end
140+
return true
141+
end
132142

133143
function evalfr(f::SisoZpk{T1,TR}, s::T2) where {T1<:Number, TR<:Number, T2<:Number}
134144
T0 = promote_type(T2, TR)

0 commit comments

Comments
 (0)