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

Generic types #118

Merged
merged 120 commits into from
Sep 2, 2018
Merged
Show file tree
Hide file tree
Changes from 79 commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
276d8a0
Add some simulators
baggepinnen Jan 25, 2018
1d83ad9
Update gain scheduling example
baggepinnen Jan 25, 2018
9dd5e81
gain scheduling working
baggepinnen Jan 25, 2018
bd7c453
Update gain scheduling
baggepinnen Jan 25, 2018
519e3f8
Implement continuous simulation through lsim
baggepinnen Jan 25, 2018
14f4a87
update gainscheduling example notebook
baggepinnen Jan 25, 2018
0a28150
Update notebook
baggepinnen Jan 25, 2018
ccd96f3
update gs notebook
baggepinnen Jan 26, 2018
0c20a3a
update gs notebook
baggepinnen Jan 26, 2018
f706c8a
Fix gs bug and add gs test
baggepinnen Jan 26, 2018
9ad767b
Update gs notebook
baggepinnen Jan 26, 2018
71c3477
update gs notebook
baggepinnen Jan 26, 2018
c4e28db
update gs notebook
baggepinnen Jan 26, 2018
75e9354
update gs
baggepinnen Jan 27, 2018
7f4aa89
Making types more generic
baggepinnen Jan 27, 2018
b2db44a
Some progress
baggepinnen Jan 27, 2018
ba95330
Progress on type system
baggepinnen Jan 28, 2018
7090ba8
more work
baggepinnen Jan 28, 2018
43a7d2e
progress
baggepinnen Jan 28, 2018
7457d60
add example
baggepinnen Jan 28, 2018
0c1f30f
Merge branch 'autodiff' of git://github.com/JuliaControl/ControlSyste…
baggepinnen Jan 28, 2018
504595a
work
baggepinnen Jan 28, 2018
96df163
work
baggepinnen Jan 29, 2018
0ef8378
work
baggepinnen Jan 29, 2018
b81776c
10ish errors left
baggepinnen Jan 29, 2018
72a7231
update autodiff example
baggepinnen Jan 29, 2018
591a544
Revert gs example to Interact
baggepinnen Jan 30, 2018
4d5d35d
Add using plots statement
baggepinnen Jan 30, 2018
7b9fbc6
Bugfix
baggepinnen Jan 30, 2018
b738041
upda gs notebook
baggepinnen Jan 30, 2018
8f363b5
All tests pass
baggepinnen Jan 30, 2018
e750480
Add promotion tests and make them pass
baggepinnen Jan 31, 2018
fe650ed
update syntax of ODE solvers
baggepinnen Feb 1, 2018
f34a849
Making types more generic
baggepinnen Jan 27, 2018
82e8894
Some progress
baggepinnen Jan 27, 2018
e6eddad
Progress on type system
baggepinnen Jan 28, 2018
902cdd8
more work
baggepinnen Jan 28, 2018
87aa1fb
progress
baggepinnen Jan 28, 2018
0137ed6
add example
baggepinnen Jan 28, 2018
b6f9926
work
baggepinnen Jan 28, 2018
ff0fc34
work
baggepinnen Jan 29, 2018
e3d742d
work
baggepinnen Jan 29, 2018
9b4c034
10ish errors left
baggepinnen Jan 29, 2018
429fb03
update autodiff example
baggepinnen Jan 29, 2018
9786049
All tests pass
baggepinnen Jan 30, 2018
cf56f2b
Add promotion tests and make them pass
baggepinnen Jan 31, 2018
5e40125
Review comments
baggepinnen Feb 1, 2018
a61046a
Merge
baggepinnen Feb 1, 2018
2633163
step and impulse cont. time and tests
baggepinnen Feb 1, 2018
562772d
Update readme and example
baggepinnen Feb 1, 2018
19d5247
Bugfix in simulators
baggepinnen Feb 1, 2018
dc25cf7
update gs notebook
baggepinnen Feb 1, 2018
51960a9
Fix weird method adding bug
baggepinnen Feb 2, 2018
e3a1eec
update gs notebook
baggepinnen Feb 3, 2018
f40a05c
Update autodiff example
baggepinnen Feb 4, 2018
07ee21d
update gs notebook
baggepinnen Feb 4, 2018
b611883
update gs notebook
baggepinnen Feb 5, 2018
eabf6d4
update simulators
baggepinnen Feb 6, 2018
d596b07
Fix #125
baggepinnen Feb 6, 2018
5e95f52
Update simulators to use mutating dynamics function
baggepinnen Feb 7, 2018
23a0048
Fix feedback(P,C)
baggepinnen Feb 7, 2018
7653b62
fix feedback(P,C) and minreal
baggepinnen Feb 7, 2018
4312dbb
Update simulator
baggepinnen Feb 7, 2018
c0bb7c9
fix gs bug
baggepinnen Feb 7, 2018
2c6d374
Revert solver face
baggepinnen Feb 8, 2018
7d8dc47
remove ipynb checkpoints
baggepinnen Feb 11, 2018
1bb34ac
move example ipynb to example repo
baggepinnen Feb 11, 2018
f6e2a4f
Update sisozpk.jl
olof3 Feb 26, 2018
e0bb7c5
Fix stack overflow error
baggepinnen Mar 14, 2018
3d17d43
Work on type system.
olof3 Apr 6, 2018
1a194f4
WIP, some updates, for mfalt to fix bug.
olof3 Apr 13, 2018
78ed0ab
minor promotion conversion fix
mfalt Jun 16, 2018
566033d
Deactivate plot tests
baggepinnen Jun 16, 2018
d94d8a5
Fix statespace tests
baggepinnen Jun 16, 2018
43d816a
Remove generalized transfer functions
baggepinnen Jun 16, 2018
9cd63ff
Remove more generalized
baggepinnen Jun 16, 2018
2d9b537
remove special case simulators
baggepinnen Jun 16, 2018
8c26997
Fix some tests
baggepinnen Jun 16, 2018
3becd67
Fixes to zpk types and tests.
olof3 Jun 17, 2018
2808f6e
Some fixes and quickfixes to analysis tests.
olof3 Jun 17, 2018
78bd1eb
Minor fixes for dcgain.
olof3 Jun 17, 2018
e696414
Conversion bugs
mfalt Jun 20, 2018
bc5eb45
Almost all errors fixed
mfalt Jun 20, 2018
5cc05fc
Complex additions and missing file
mfalt Jun 20, 2018
e9722d0
1 -> one(T)
baggepinnen Jun 21, 2018
476f65f
Merge branch 'autodiff' of git://github.com/JuliaControl/ControlSyste…
baggepinnen Jun 21, 2018
d062189
Fixed printing of complex zpk models.
olof3 Jun 21, 2018
c1dea17
work on hvcat macro
mfalt Jun 21, 2018
1bc4fd8
@sys macro now working, bug with ss
mfalt Jun 22, 2018
14f83a2
hcat and vcat fixed, 5 broken
mfalt Jun 25, 2018
f965712
Merge pull request #139 from JuliaControl/hvcat
mfalt Jun 25, 2018
e15f50a
Minor fixes and tests
mfalt Jun 25, 2018
fff824b
Conversion Matrix{Number} -> Statespace + tests
olof3 Jun 26, 2018
8eb94d8
Updates.
olof3 Jun 26, 2018
6c1d023
Merge pull request #142 from JuliaControl/mat2ss_conversion
mfalt Jun 26, 2018
77b8240
eltype and numeric_type update
mfalt Jun 26, 2018
e4e7496
Merge pull request #143 from JuliaControl/eltype2
olof3 Jun 26, 2018
4e1711f
Misc. fixes.
olof3 Jun 26, 2018
87ea381
Fixed parenthesizing for printing gain of zpk models.
olof3 Jun 26, 2018
dd92d27
More fixes.
olof3 Jun 27, 2018
24ba60b
More fixes.
olof3 Jun 27, 2018
8abee9a
Make freqresp/evalfr account for numeric typs of s/w, e.g., if SymPy.…
olof3 Jun 28, 2018
7024e09
TransferFunction Type def. and direct conversion ss->zpk
olof3 Jun 29, 2018
143344f
Example with symbplic computations.
olof3 Jun 29, 2018
969db22
More fixes, e.g., equality of transfer functions, types of zpk models.
olof3 Jun 30, 2018
c22613b
Merge branch 'autodiff' of git://github.com/JuliaControl/ControlSyste…
baggepinnen Jul 30, 2018
6520924
Add missing type
baggepinnen Jul 30, 2018
5bf3f01
Delete accidentally added fields
baggepinnen Jul 30, 2018
0db1de1
Merge branch 'autodiff' into misc_fixes
mfalt Jul 30, 2018
c76ed70
Merge pull request #144 from JuliaControl/misc_fixes
mfalt Jul 30, 2018
97358b3
work on verifying types
mfalt Aug 8, 2018
ea3c03e
small fixes and work towards test
mfalt Aug 15, 2018
cf00a02
more minor fixes and work towards tests
mfalt Aug 15, 2018
1e48eed
some sort of working type test
mfalt Aug 16, 2018
c58b7fc
more fixes to tests and more stable norminf function
mfalt Aug 17, 2018
923a0cd
Update conversion.jl
baggepinnen Aug 29, 2018
af834df
Fixed some type problems and bugs, tests should pass
mfalt Sep 2, 2018
4c81d97
Merge branch 'autodiff' into typetest
mfalt Sep 2, 2018
0d436c8
Some mmore fixes
mfalt Sep 2, 2018
d77d86d
Merge pull request #147 from JuliaControl/typetest
mfalt Sep 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,27 @@ To install, in the Julia REPL:
```julia
Pkg.add("ControlSystems")
```

Note that the latest version of this package requires Julia 0.5. Users of Julia 0.4 should use [v0.1.4](https://github.com/JuliaControl/ControlSystems.jl/tree/v0.1.4) instead.

## News
### 2018-02-01
- LTISystem types are now more generic and can hold matrices/vectors of arbitrary type. Examples (partly pseudo-code):
```julia
ss(1)
ss(1.)
ss(1im)
ss(ForwardDiff.Dual(1.))
ss(GPUArray([1]))
ss(SparseMatrix([1])
```
Similar for `tf,zpk` etc.
- Continuous time systems are simulated with continuous time solvers from `OrdinaryDiffEq.jl`
- Breaking: `lsim(sys, u::Function)` syntax has changed from `u(t,x)` to `u(x,t)` to be consistent with `OrdinaryDiffEq`
- Breaking: `feedback(P,C)` no longer returns `feedback(P*C)`. The behavior is changed to `feedback(P1, P2) = P1/(1+P1*P2)`.
- Type `Simulator` provides lower level interface to continuous time simulation.
- Example [autodiff.jl](https://github.com/JuliaControl/ControlSystems.jl/tree/master/example/autodiff.jl) provides an illustration of how the new generic types can be used for automatic differentiation of a cost function through the continuous-time solver, which allows for optimization of the cost function w.r.t. PID parameters.


## Documentation

All functions have docstrings, which can be viewed from the REPL, using for example `?tf `.
Expand Down
3 changes: 2 additions & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ julia 0.6.0
Plots 0.7.4
Polynomials
LaTeXStrings
Requires
OrdinaryDiffEq
IterTools
1 change: 0 additions & 1 deletion docs/src/lib/constructors.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ sminreal
ss
ss2tf
tf
tfg
zpk
```
20 changes: 0 additions & 20 deletions docs/src/man/creatingtfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,6 @@ Continuous-time transfer function model

The transfer functions created using this method will be of type `TransferFunction{SisoZpk}`.

## tfg - Generalized Representation
If you want to work with transfer functions that are not rational functions, it is possible to use the `tfg` representation
```julia
tfg(str::String), tfg(str::Expr)
```
This function will either convert `str` to an expression or directly accept an `Expr` and create a transfer function.
### Example:
```julia
tfg("1/((s+1)*exp(-sqrt(s)))")

## output

TransferFunction:
1/((s+1)*exp(-sqrt(s)))

Continuous-time transfer function model
```
The transfer functions created using this method will be of type `TransferFunction{SisoGeneralized}`.
This type will work with some functions like `bodeplot, stepplot` but not others ,like `poles`.

## Converting between types
It is sometime useful to convert one representation to another, this is possible using the same functions, for example
```julia
Expand Down
114 changes: 114 additions & 0 deletions example/autodiff.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using ControlSystems, OrdinaryDiffEq, NLopt, BlackBoxOptim
p0 = Float64[0.2,0.8,1] # Initial guess
K(kp,ki,kd) = pid(kp=kp, ki=ki, kd=kd)
K(p) = K(p...)

# Define process model
ζ = 0.1
ω = 1.; ω² = ω^2
P = tf(ω²,[1, 2ζ*ω, ω²])*tf(1,[1,1])

Ω = logspace(-1,2,150) # Frequency vector to eval constraints
h = 0.1 # Sample time for time-domain evaluation
Tf = 60. # Time horizon
t = 0:h:Tf-h

Ms = 1.4 # Maximum allowed magnitude of sensitivity function
Mt = 1.4 # Maximum allowed magnitude of complimentary sensitivity function

p = copy(p0)

function timedomain(p)
C = K(p[1], p[2], p[3])
S = 1/(1+P*C) # Sensitivity fun
PS = ss(P*S) # TF from load disturbance to output
s = Simulator(PS, (t,x) -> [1]) # Sim. unit step load disturbance
ty = eltype(p) # So that all inputs to solve have same numerical type (ForwardDiff.Dual)
x0 = zeros(PS.nx) .|> ty
tspan = (ty(0.),ty(Tf))
sol = solve(s, x0, tspan, Tsit5())
y = PS.C*sol(t) # y = C*x
C,y
end

function freqdomain(p)
C = K(p[1], p[2], p[3])
S = 1/(1+P*C) # Sensitivity fun
T = tf(1.) - S# Comp. Sensitivity fun
Sw = vec(bode(S,Ω)[1]) # Freq. domain constraints
Tw = vec(bode(T,Ω)[1]) # Freq. domain constraints
Sw,Tw
end

# Evaluates and plots candidate controller
function evalsol(p::Vector)
C,y = timedomain(p)
Sw,Tw = freqdomain(p)
plot(t,y', layout=2, show=false)
plot!(Ω, [Sw Tw] , lab=["Sw" "Tw"], subplot=2, xscale=:log10, yscale=:log10, show=false)
plot!([Ω[1],Ω[end]], [Ms,Ms], c = :black, l=:dash, subplot=2, show=false, lab="Ms")
plot!([Ω[1],Ω[end]], [Mt,Mt], c = :purple, l=:dash, subplot=2, lab="Mt")
gui()
false
end
evalsol(res::BlackBoxOptim.OptimizationResults) = evalsol(best_candidate(res))


function constraintfun(p)
Sw,Tw = freqdomain(p)
[maximum(Sw)-Ms; maximum(Tw)-Mt]
end


function costfun(p)
C,y = timedomain(p)
mean(abs,y) # ~ Integrated absolute error IAE
end


function runopt(p, costfun, constraintfun;
f_tol = 1e-5,
x_tol = 1e-3,
c_tol = 1e-8,
f_cfg = ForwardDiff.GradientConfig(costfun, p),
g_cfg = ForwardDiff.JacobianConfig(constraintfun, p),
lb = zeros(length(p)))

c1 = constraintfun(p)
np = length(p)
nc = length(c1)

function f(p::Vector, grad::Vector)
if length(grad) > 0
grad .= ForwardDiff.gradient(costfun,p,f_cfg)
end
costfun(p)
end

function c(result, p::Vector, grad)
if length(grad) > 0
grad .= ForwardDiff.jacobian(constraintfun,p,g_cfg)'
end
result .= constraintfun(p)
end

opt = Opt(:LD_SLSQP, np)
lower_bounds!(opt, lb)
xtol_rel!(opt, x_tol)
ftol_rel!(opt, f_tol)

min_objective!(opt, f)
inequality_constraint!(opt, c, c_tol*ones(nc))
minf,minx,ret = NLopt.optimize(opt, p)
end

f_cfg = ForwardDiff.GradientConfig(costfun, p)
g_cfg = ForwardDiff.JacobianConfig(constraintfun, p)
@time minf,minx,ret = runopt(1p0, costfun, constraintfun, x_tol=1e-6, c_tol=1e-12, f_cfg=f_cfg, g_cfg=g_cfg)
evalsol(minx)

# # Optimize costfun using derivative-free method
# res1 = compare_optimizers(costfun; SearchRange = (0.,2.), NumDimensions = length(p0), MaxTime = 20.0)
# res2 = bboptimize(costfun, NumDimensions = length(p0), MaxTime = 20.0)
# evalsol(res2)
# p = best_candidate(res2)
Empty file added example/gks.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 45 additions & 13 deletions src/ControlSystems.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
module ControlSystems

const BlasNumber = Union{Base.LinAlg.BlasFloat, Base.LinAlg.BlasInt} # QUESTION: WHy include BlasInt, why not include BlasComplex?

export LTISystem,
StateSpace,
TransferFunction,
ss,
tf,
tfg,
zpk,
ss2tf,
LQG,
primitivetype,
# Linear Algebra
balance,
care,
Expand Down Expand Up @@ -57,6 +59,8 @@ export LTISystem,
step,
impulse,
lsim,
solve,
Simulator,
# Frequency Response
freqresp,
evalfr,
Expand All @@ -67,27 +71,55 @@ export LTISystem,
numpoly,
denpoly

using Plots, LaTeXStrings, Requires

# QUESTION: are these used? LaTeXStrings, Requires, IterTools
using Polynomials, OrdinaryDiffEq, Plots
import Base: +, -, *, /, (./), (==), (.+), (.-), (.*), (!=), isapprox, convert, promote_op

include("types/lti.jl")
include("types/transferfunction.jl")
include("types/statespace.jl")
include("types/tf2ss.jl")
include("types/lqg.jl")
abstract type AbstractSystem end

include("types/Lti.jl")

abstract type SisoTf{T<:Number} end

# Transfer functions and tranfer function elemements
include("types/TransferFunction.jl")
include("types/SisoTfTypes/SisoZpk.jl")
include("types/SisoTfTypes/SisoRational.jl")
include("types/SisoTfTypes/promotion.jl")
include("types/SisoTfTypes/conversion.jl")

include("types/StateSpace.jl")

# Convenience constructors
include("types/tf.jl")
include("types/zpk.jl")
include("types/ss.jl")

include("types/lqg.jl") # QUESTION: is it really motivated to have an LQG type?

include("utilities.jl")

include("types/promotion.jl")
include("types/conversion.jl")
include("connections.jl")
include("discrete.jl")

# Analysis
include("freqresp.jl")
include("timeresp.jl")

include("matrix_comps.jl")
include("simplification.jl")
include("synthesis.jl")

include("discrete.jl")
include("analysis.jl")
include("timeresp.jl")
include("freqresp.jl")
include("utilities.jl")
include("plotting.jl")
include("synthesis.jl")

include("simulators.jl")
include("pid_design.jl")



# The path has to be evaluated upon initial import
const __CONTROLSYSTEMS_SOURCE_DIR__ = dirname(Base.source_path())

Expand Down
48 changes: 18 additions & 30 deletions src/analysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,11 @@ pole(sys::SisoTf) = error("pole is not implemented for type $(typeof(sys))")

@doc """`dcgain(sys)`

Compute the gain of SISO system `sys`.""" ->
function dcgain(sys::StateSpace, zs::Vector=tzero(sys))
!issiso(sys) && error("Gain only defined for siso systems")
return ( sys.C*(-sys.A\sys.B) + sys.D)[1]
end

@doc """`dcgain(sys)`

Compute the dcgain of system `sys`.

equal to G(0) for continuous-time systems and G(1) for discrete-time systems.""" ->
function dcgain(sys::TransferFunction)
!issiso(sys) && error("Gain only defined for siso systems")
if sys.Ts > 0
return map(s->sum(s.num.a)/sum(s.den.a), sys.matrix)
end

return map(s -> s.num[end]/s.den[end], sys.matrix)
function dcgain(sys::LTISystem)
return sys.Ts > 0 ? evalfr(sys, 1) : evalfr(sys, 0)
end

@doc """`markovparam(sys, n)`
Expand Down Expand Up @@ -78,12 +65,13 @@ function _zpk_kern(sys::TransferFunction, iy::Int, iu::Int)
return _zpk_kern(s)
end

function _zpk_kern(s::SisoRational)
return roots(s.num), roots(s.den), s.num[1]/s.den[1]
function _zpk_kern(f::SisoRational)
f_zpk = convert(SisoZpk, f)
return f_zpk.z, f_zpk.p, f_zpk.k
end

function _zpk_kern(s::SisoZpk)
return s.z, s.p, s.k
function _zpk_kern(f::SisoZpk)
return f.z, f.p, f.k
end

@doc """`Wn, zeta, ps = damp(sys)`
Expand Down Expand Up @@ -142,8 +130,8 @@ end
#
# Note that this returns either Vector{Complex64} or Vector{Float64}
tzero(sys::StateSpace) = tzero(sys.A, sys.B, sys.C, sys.D)
function tzero(A::Matrix{Float64}, B::Matrix{Float64}, C::Matrix{Float64},
D::Matrix{Float64})
function tzero(A::Matrix{<:BlasNumber}, B::Matrix{<:BlasNumber}, C::Matrix{<:BlasNumber},
D::Matrix{<:BlasNumber})
# Balance the system
A, B, C = balance_statespace(A, B, C)

Expand Down Expand Up @@ -176,7 +164,7 @@ end
Implements REDUCE in the Emami-Naeini & Van Dooren paper. Returns transformed
A, B, C, D matrices. These are empty if there are no zeros.
"""
function reduce_sys(A::Matrix{Float64}, B::Matrix{Float64}, C::Matrix{Float64}, D::Matrix{Float64}, meps::Float64)
function reduce_sys(A::Matrix{<:BlasNumber}, B::Matrix{<:BlasNumber}, C::Matrix{<:BlasNumber}, D::Matrix{<:BlasNumber}, meps::BlasNumber)
Cbar, Dbar = C, D
if isempty(A)
return A, B, C, D
Expand Down Expand Up @@ -230,10 +218,10 @@ end

# Determine the number of non-zero rows, with meps as a tolerance. For an
# upper-triangular matrix, this is a good proxy for determining the row-rank.
function fastrank(A::Matrix{Float64}, meps::Float64)
function fastrank(A::AbstractMatrix, meps::Real)
n, m = size(A, 1, 2)
if n*m == 0 return 0 end
norms = Array{Float64}(n)
norms = Vector{eltype(A)}(n)
for i = 1:n
norms[i] = norm(A[i, :])
end
Expand All @@ -256,11 +244,11 @@ function margin{S<:Real}(sys::LTISystem, w::AbstractVector{S}; full=false, allMa
vals = (:wgm, :gm, :wpm, :pm, :fullPhase)
if allMargins
for val in vals
eval(:($val = Array{Array{Float64,1}}($ny,$nu)))
eval(:($val = Array{Array{eltype(sys),1}}($ny,$nu)))
end
else
for val in vals
eval(:($val = Array{Float64,2}($ny,$nu)))
eval(:($val = Array{eltype(sys),2}($ny,$nu)))
end
end
for j=1:nu
Expand Down Expand Up @@ -337,17 +325,17 @@ end

function _allPhaseCrossings(w, phase)
#Calculate numer of times real axis is crossed on negative side
n = Array{Float64,1}(length(w)) #Nbr of crossed
ph = Array{Float64,1}(length(w)) #Residual
n = Vector{eltype(w)}(length(w)) #Nbr of crossed
ph = Vector{eltype(w)}(length(w)) #Residual
for i = eachindex(w) #Found no easier way to do this
n[i], ph[i] = fldmod(phase[i]+180,360)#+180
end
_findCrossings(w, n, ph)
end

function _findCrossings(w, n, res)
wcross = Array{Float64,1}()
tcross = Array{Float64,1}()
wcross = Vector{eltype(w)}()
tcross = Vector{eltype(w)}()
for i in 1:(length(w)-1)
if res[i] == 0
wcross = [wcross; w[i]]
Expand Down
Loading