Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zpk conjugate pairup fails on 0.0 and -0.0 #674

Merged
merged 1 commit into from
May 18, 2022
Merged

Conversation

albheim
Copy link
Member

@albheim albheim commented Mar 17, 2022

I ran in to this just now, seems like this should fix it.

Problem is that

julia> isequal(0.0, -0.0)
false

julia> ==(0.0, -0.0)
true
julia> H = tf([0.65, 0, 0.45], [1, 0, 0], 0.2)
TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}
0.65z^2 + 0.45
--------------
    1.0z^2

Sample Time: 0.2 (seconds)
Discrete-time transfer function model

julia> bodeplot(H)
ERROR: ArgumentError: zpk model should be real-valued, but zeros do not come in conjugate pairs.
Stacktrace:
  [1] ControlSystems.SisoZpk{Float64, ComplexF64}(z::Vector{ComplexF64}, p::Vector{ComplexF64}, k::Float64)
    @ ControlSystems ~/.julia/packages/ControlSystems/lbxGy/src/types/SisoTfTypes/SisoZpk.jl:16
  [2] ControlSystems.SisoZpk{Float64, ComplexF64}(z::Vector{ComplexF64}, p::Vector{Float64}, k::Float64)
    @ ControlSystems ~/.julia/packages/ControlSystems/lbxGy/src/types/SisoTfTypes/SisoZpk.jl:23
  [3] convert(#unused#::Type{ControlSystems.SisoZpk{Float64, ComplexF64}}, f::ControlSystems.SisoRational{Float64})
    @ ControlSystems ~/.julia/packages/ControlSystems/lbxGy/src/types/SisoTfTypes/conversion.jl:8
  [4] convert
    @ ~/.julia/packages/ControlSystems/lbxGy/src/types/SisoTfTypes/conversion.jl:14 [inlined]
  [5] _broadcast_getindex_evalf
    @ ./broadcast.jl:670 [inlined]
  [6] _broadcast_getindex
    @ ./broadcast.jl:653 [inlined]
  [7] getindex
    @ ./broadcast.jl:597 [inlined]
  [8] copy
    @ ./broadcast.jl:899 [inlined]
  [9] materialize
    @ ./broadcast.jl:860 [inlined]
 [10] convert(#unused#::Type{TransferFunction{Discrete{Float64}, ControlSystems.SisoZpk}}, G::TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}})
    @ ControlSystems ~/.julia/packages/ControlSystems/lbxGy/src/types/conversion.jl:60
 [11] zpkdata
    @ ~/.julia/packages/ControlSystems/lbxGy/src/analysis.jl:132 [inlined]
 [12] _bounds_and_features(sys::TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}, plot::Val{:bode})
    @ ControlSystems ~/.julia/packages/ControlSystems/lbxGy/src/freqresp.jl:321
 [13] #157
    @ ~/.julia/packages/ControlSystems/lbxGy/src/freqresp.jl:307 [inlined]
 [14] iterate
    @ ./generator.jl:47 [inlined]
 [15] _collect(c::Vector{TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}}, itr::Base.Generator{Vector{TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}}, ControlSystems.var"#157#158"{Val{:bode}}}, #unused#::Base.EltypeUnknown, isz::Base.HasShape{1})
    @ Base ./array.jl:744
 [16] collect_similar(cont::Vector{TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}}, itr::Base.Generator{Vector{TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}}, ControlSystems.var"#157#158"{Val{:bode}}})
    @ Base ./array.jl:653
 [17] map(f::Function, A::Vector{TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}})
    @ Base ./abstractarray.jl:2849
 [18] _default_freq_vector(systems::Vector{TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}}, plot::Val{:bode})
    @ ControlSystems ~/.julia/packages/ControlSystems/lbxGy/src/freqresp.jl:307
 [19] _processfreqplot(plottype::Val{:bode}, systems::Vector{TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}})
    @ ControlSystems ~/.julia/packages/ControlSystems/lbxGy/src/plotting.jl:181
 [20] _processfreqplot(::Val{:bode}, ::TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}})
    @ ControlSystems ~/.julia/packages/ControlSystems/lbxGy/src/plotting.jl:173
 [21] macro expansion
    @ ~/.julia/packages/ControlSystems/lbxGy/src/plotting.jl:204 [inlined]
 [22] apply_recipe(plotattributes::AbstractDict{Symbol, Any}, p::ControlSystems.Bodeplot)
    @ ControlSystems ~/.julia/packages/RecipesBase/qpxEX/src/RecipesBase.jl:289
 [23] _process_userrecipes!(plt::Any, plotattributes::Any, args::Any)
    @ RecipesPipeline ~/.julia/packages/RecipesPipeline/oVorB/src/user_recipe.jl:36
 [24] recipe_pipeline!(plt::Any, plotattributes::Any, args::Any)
    @ RecipesPipeline ~/.julia/packages/RecipesPipeline/oVorB/src/RecipesPipeline.jl:70
 [25] _plot!(plt::Plots.Plot, plotattributes::Any, args::Any)
    @ Plots ~/.julia/packages/Plots/LI4FE/src/plot.jl:208
 [26] plot(args::Any; kw::Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}})
    @ Plots ~/.julia/packages/Plots/LI4FE/src/plot.jl:91
 [27] plot
    @ ~/.julia/packages/Plots/LI4FE/src/plot.jl:85 [inlined]
 [28] bodeplot(::TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}, ::Vararg{Any}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ ControlSystems ~/.julia/packages/RecipesBase/qpxEX/src/RecipesBase.jl:364
 [29] bodeplot(::TransferFunction{Discrete{Float64}, ControlSystems.SisoRational{Float64}}, ::Vararg{Any})
    @ ControlSystems ~/.julia/packages/RecipesBase/qpxEX/src/RecipesBase.jl:364
 [30] top-level scope
    @ REPL[41]:1

@JuliaControlBot
Copy link

This is an automated message.
Plots were compared to references. 7/11 images have changed, see differences below.
After pulling this PR, please update the reference images by creating a PR to ControlExamplePlots.jl here.

Difference Reference Image New Image
❌ 0.048 Reference New
✔️ 0.001 Reference New
✔️ 0.001 Reference New
✔️ 0.0 Reference New
❌ 0.043 Reference New
❌ 0.046 Reference New
✔️ 0.01 Reference New

@codecov
Copy link

codecov bot commented Mar 17, 2022

Codecov Report

Merging #674 (f49b6f0) into master (a8a53ac) will not change coverage.
The diff coverage is 100.00%.

@@           Coverage Diff           @@
##           master     #674   +/-   ##
=======================================
  Coverage   87.33%   87.33%           
=======================================
  Files          34       34           
  Lines        3522     3522           
=======================================
  Hits         3076     3076           
  Misses        446      446           
Impacted Files Coverage Δ
src/types/SisoTfTypes/SisoZpk.jl 69.06% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a8a53ac...f49b6f0. Read the comment docs.

@JuliaControlBot
Copy link

This is an automated message.
Plots were compared to references. 7/11 images have changed, see differences below.
After pulling this PR, please update the reference images by creating a PR to ControlExamplePlots.jl here.

Difference Reference Image New Image
❌ 0.048 Reference New
✔️ 0.001 Reference New
✔️ 0.001 Reference New
✔️ 0.0 Reference New
❌ 0.043 Reference New
❌ 0.046 Reference New
✔️ 0.01 Reference New

@baggepinnen
Copy link
Member

Hmm, that's a bit unfortunate, isequal was used to work with symbolic coefficients. I wonder if there's a solution that works in both cases.

@albheim
Copy link
Member Author

albheim commented Mar 17, 2022

Ahh, that is annoying. Why does symbolics need isequal rather than ==?

@baggepinnen
Copy link
Member

a==b with symbols produces a symbolic expression rather than a Bool. isequal always results in a Bool.

@albheim
Copy link
Member Author

albheim commented Mar 18, 2022

Hmm, not sure I like that. It seems like it would make it problematic to handle both symbolics and numerics with the same code as soon as you want to compare any of the numbers then?

The docs for == say

The result is of type Bool, except when one of the operands is missing, in
  which case missing is returned (three-valued logic
  (https://en.wikipedia.org/wiki/Three-valued_logic)). 

which even though possible to not get bool, it should then return missing. Isn't it frowned upon to add other meaning to operators defined in Base?

@baggepinnen baggepinnen merged commit f57b89e into master May 18, 2022
@baggepinnen baggepinnen deleted the albheim/pairup_conj branch May 18, 2022 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants