Skip to content
SlewRateLimiterTest.md

SlewRateLimiterTest

Test component that validates SlewRateLimiter behavior with a sinusoidal input.

This test component connects a sine wave generator to a slew rate limiter and verifies the expected output value after simulation. The slew rate limiter restricts how quickly the output signal can change, with separate limits for rising and falling rates. The sine input provides a continuously changing signal that exercises both the rising and falling rate limits.

Usage

SlewRateLimiterTest()

Behavior

sine.y(t)=limiter.u(t)dlimiter.y(t)dt=clamp(limiter.u(t)limiter.y(t)limiter.td,limiter.falling,limiter.rising)sine.y(t)=ifelse(sine.start_time<t,sine.offset+sine.amplitudesin(sine.phase+6.2832sine.frequency(sine.start_time+t)),sine.offset)

Source

dyad
# Test component that validates SlewRateLimiter behavior with a sinusoidal input.
#
# This test component connects a sine wave generator to a slew rate limiter and verifies the expected
# output value after simulation. The slew rate limiter restricts how quickly the output signal can change,
# with separate limits for rising and falling rates. The sine input provides a continuously changing signal
# that exercises both the rising and falling rate limits.
test component SlewRateLimiterTest
  # Slew rate limiter instance with rising/falling limits and small time delay
  limiter = SlewRateLimiter(rising=1, falling=-1, td=0.001)
  # Sine wave generator producing a 2Hz signal with amplitude 2
  sine = Sine(amplitude=2, frequency=2)
relations
  # Connects the sine wave output to the slew rate limiter input
  connect(sine.y, limiter.u)
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 1,
        "expect": {"signals": ["limiter.y"], "final": {"limiter.y": -0.040594643}}
      }
    }
  }
}
end
Flattened Source
dyad
# Test component that validates SlewRateLimiter behavior with a sinusoidal input.
#
# This test component connects a sine wave generator to a slew rate limiter and verifies the expected
# output value after simulation. The slew rate limiter restricts how quickly the output signal can change,
# with separate limits for rising and falling rates. The sine input provides a continuously changing signal
# that exercises both the rising and falling rate limits.
test component SlewRateLimiterTest
  # Slew rate limiter instance with rising/falling limits and small time delay
  limiter = SlewRateLimiter(rising=1, falling=-1, td=0.001)
  # Sine wave generator producing a 2Hz signal with amplitude 2
  sine = Sine(amplitude=2, frequency=2)
relations
  # Connects the sine wave output to the slew rate limiter input
  connect(sine.y, limiter.u)
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 1,
        "expect": {"signals": ["limiter.y"], "final": {"limiter.y": -0.040594643}}
      }
    }
  }
}
end


Test Cases

This is setup code, that must be run before each test case.

julia
using BlockComponents
using ModelingToolkit, OrdinaryDiffEqDefault
using Plots
using CSV, DataFrames

snapshotsdir = joinpath(dirname(dirname(pathof(BlockComponents))), "test", "snapshots")
"/home/actions-runner-10/.julia/packages/BlockComponents/77kIK/test/snapshots"

Test Case case1

julia
@mtkbuild model_case1 = SlewRateLimiterTest()
u0_case1 = []
prob_case1 = ODEProblem(model_case1, u0_case1, (0, 1))
sol_case1 = solve(prob_case1)
retcode: Success
Interpolation: 3rd order Hermite
t: 27-element Vector{Float64}:
 0.0
 9.999999999999999e-5
 0.0001625224612434168
 0.0007877470736775845
 0.007039993198019262
 0.06956245444143604
 0.23765155374686753
 0.29850850733521644
 0.32508077634378724
 0.4856167673571994

 0.7297253797520752
 0.7711076765228725
 0.7889884164724102
 0.9677958159677874
 0.9833640924685384
 0.9918878571083547
 0.9948558434220218
 0.9973099728864305
 1.0
u: 27-element Vector{Vector{Float64}}:
 [0.0]
 [8.055743568657085e-5]
 [0.00014307989692998761]
 [0.0007683045093641553]
 [0.007020550633705832]
 [0.0695430118771226]
 [0.23763211118255403]
 [0.18851577441289225]
 [0.16194350540432145]
 [0.0014075143909093668]

 [0.21864333768278216]
 [0.18607222300580853]
 [0.16819148305627082]
 [-0.01061591643910627]
 [-0.026184192939857215]
 [-0.03470795757967352]
 [-0.03767594389334064]
 [-0.04013007335774929]
 [-0.04059464328499656]
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.limiter.y])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "SlewRateLimiterTest_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.limiter.y], width=2, label="Actual value of limiter.y")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of limiter.y")
end
scatter!(plt, [df_case1.t[end]], [-0.040594643], label="Final Condition for `limiter.y`")

plt