Input Signal Generation
This page describes the input signal generation capabilities of ControlSystemIdentification.jl. The InputSignals
submodule provides functions for generating various types of excitation signals commonly used in system identification.
Overview
Proper excitation signal design is crucial for successful system identification. The quality of the input signal directly affects the quality of the identified model. This package provides several standard signal types:
- PRBS (Pseudo-Random Binary Sequence): Binary signals with white noise-like properties
- Chirp signals: Frequency sweeps for analyzing system response across frequency ranges
- Multi-sine signals: Controlled spectral content at specific frequencies
- Step signals: Fundamental for transient response analysis
PRBS (Pseudo-Random Binary Sequence)
ControlSystemIdentification.InputSignals.prbs
— Functionprbs(N; low=-1, high=1, seed=nothing, period=1)
Generate a Pseudo-Random Binary Sequence (PRBS) of length N
.
A PRBS is a deterministic signal that approximates white noise properties while taking only two amplitude values. It's widely used in system identification due to its flat power spectrum and ease of generation.
Arguments
N::Int
: Length of the sequencelow::Real=-1
: Lower amplitude value (default: -1)high::Real=1
: Upper amplitude value (default: 1)seed::Union{Int,Nothing}=nothing
: Random seed for reproducibilityperiod::Int=1
: Minimum number of samples before the signal can change (dominant period)
Returns
Vector{Float64}
: PRBS signal of length N with values alternating betweenlow
andhigh
Examples
# Generate a standard PRBS with values {-1, 1}
u = prbs(100)
# Generate a PRBS with custom amplitude levels
u = prbs(100; low=0, high=5)
# Generate a reproducible PRBS
u = prbs(100; seed=42)
# Generate a slower PRBS that holds values for at least 5 samples
u = prbs(100; period=5)
Notes
- The algorithm uses the sign of normally distributed random numbers to generate the binary sequence. While not a true maximal-length sequence, it provides good statistical properties for system identification purposes.
- The
period
parameter controls the spectral content by setting a minimum hold time, effectively creating a low-pass characteristic in the signal spectrum.
Example
using ControlSystemIdentification, Plots
# Generate a standard PRBS signal
N = 200
u_prbs = prbs(N; seed=42)
# Generate a PRBS with custom amplitude levels
u_custom = prbs(N; low=0, high=5, seed=42)
# Generate a slower PRBS with period=10 (holds values for 10 samples)
u_slow = prbs(N; period=10, seed=42)
# Plot the signals
p1 = plot(u_prbs, title="Standard PRBS", xlabel="Sample", ylabel="Amplitude",
label="u(t)", linewidth=2)
p2 = plot(u_custom, title="Custom PRBS (0 to 5)", xlabel="Sample", ylabel="Amplitude",
label="u(t)", linewidth=2)
p3 = plot(u_slow, title="Slow PRBS (period=10)", xlabel="Sample", ylabel="Amplitude",
label="u(t)", linewidth=2)
plot(p1, p2, p3, layout=(3,1), size=(600, 600))
Chirp Signals
ControlSystemIdentification.InputSignals.chirp
— Functionchirp(N; Ts, f0, f1, logspace=true)
Generate a chirp (frequency sweep) signal of length N
.
A chirp signal is a sinusoidal signal whose frequency changes over time. It's useful for system identification as it excites the system across a range of frequencies.
Arguments
N::Int
: Length of the signalTs::Real
: Sample timef0::Real
: Starting frequency (Hz)f1::Real
: Ending frequency (Hz)logspace::Bool=true
: If true, use logarithmic frequency spacing; if false, use linear
Returns
Vector{Float64}
: Chirp signal
Examples
# Generate a logarithmic chirp from 0.1 to 10 Hz
u = chirp(1000, Ts=0.01, f0=0.1, f1=10.0)
# Generate a linear chirp
u = chirp(1000, Ts=0.01, f0=0.1, f1=10.0, logspace=false)
Notes
- Logarithmic spacing is often preferred for system identification as it provides equal energy per frequency decade
- The signal amplitude is normalized to ±1
Example
# Generate chirp signals
N = 1000
Ts = 0.01
f0 = 1.0 # Start frequency (Hz)
f1 = 10.0 # End frequency (Hz)
u_log = chirp(N; Ts, f0, f1, logspace=true)
u_lin = chirp(N; Ts, f0, f1, logspace=false)
# Time vector for plotting
t = (0:N-1) * Ts
# Plot time domain signals
p1 = plot(t, u_log, title="Logarithmic Chirp", xlabel="Time (s)", ylabel="Amplitude",
label="u(t)", linewidth=1)
p2 = plot(t, u_lin, title="Linear Chirp", xlabel="Time (s)", ylabel="Amplitude",
label="u(t)", linewidth=1)
plot(p1, p2, layout=(2,1), size=(600, 400))
Frequency Content Analysis
using ControlSystemIdentification.FFTW
# Analyze frequency content of the chirp signals
U_log = abs.(fft(u_log))
U_lin = abs.(fft(u_lin))
# Frequency axis (only plot positive frequencies)
freqs = (0:N-1) / (N*Ts)
half_N = N÷2
# Plot frequency domain (first half only, up to Nyquist frequency)
p1 = plot(freqs[2:half_N], U_log[2:half_N], title="Logarithmic Chirp Spectrum",
xlabel="Frequency (Hz)", ylabel="Magnitude", label="Log chirp",
xscale=:log10, yscale=:log10, linewidth=2)
p2 = plot(freqs[2:half_N], U_lin[2:half_N], title="Linear Chirp Spectrum",
xlabel="Frequency (Hz)", ylabel="Magnitude", label="Linear chirp",
xscale=:log10, yscale=:log10, linewidth=2)
vline!(p1, [f0, f1], label="", linestyle=:dash, color=:red, alpha=0.7)
vline!(p2, [f0, f1], label="", linestyle=:dash, color=:red, alpha=0.7)
plot(p1, p2, layout=(2,1), size=(600, 400))
Chirp signals are excellent for:
- Frequency response estimation
- Analyzing system behavior across frequency ranges
- Identifying resonances and anti-resonances
- Logarithmic chirps provide equal energy per frequency decade
Multi-sine Signals
ControlSystemIdentification.InputSignals.multisine
— Functionmultisine(N; frequencies, Ts)
Generate a multi-sine signal by summing sinusoidal components at specified frequencies.
Multi-sine signals are useful for system identification when you want to excite the system at specific frequencies while avoiding others (e.g., to avoid resonances).
Arguments
N::Int
: Length of the signalfrequencies::AbstractVector{<:Real}
: Vector of frequencies (Hz) to includeTs::Real
: Sample time
Returns
Vector{Float64}
: Multi-sine signal
Examples
# Generate a multi-sine with frequencies at 0.1, 1.0, and 10.0 Hz
freqs = [0.1, 1.0, 10.0]
u = multisine(1000, frequencies=freqs, Ts=0.01)
Notes
- The amplitude of each frequency component is normalized so that the total RMS value is approximately 1
- Phase of each component is randomized to minimize peak factor
Example
# Generate multi-sine signal
N = 1000
Ts = 0.01
frequencies = [0.5, 2.0, 5.0, 10.0] # Hz
u_multi = multisine(N; frequencies=frequencies, Ts)
# Time vector
t = (0:N-1) * Ts
# Plot time domain signal
p1 = plot(t, u_multi, title="Multi-sine Signal", xlabel="Time (s)", ylabel="Amplitude",
label="u(t)", linewidth=1)
# Analyze frequency content
U_multi = abs.(fft(u_multi))
freqs = (0:N-1) / (N*Ts)
half_N = N÷2
# Plot frequency domain
p2 = plot(freqs[1:half_N], U_multi[1:half_N], title="Multi-sine Spectrum",
xlabel="Frequency (Hz)", ylabel="Magnitude", label="Spectrum",
linewidth=2)
# Mark the target frequencies with vertical lines
for f in frequencies
if f <= freqs[half_N]
plot!(p2, [f, f], [0, maximum(U_multi[1:half_N])],
label="", linestyle=:dash, color=:red, alpha=0.7)
end
end
plot(p1, p2, layout=(2,1), size=(600, 400))
Multi-sine signals are ideal for:
- Avoiding problematic frequencies (resonances)
- Controlled spectral content
- Nonlinear system identification
- Minimizing peak factor (crest factor)
Step Signals
ControlSystemIdentification.InputSignals.step_signal
— Functionstep_signal(N; step_time, Ts=1.0, offset=0.0, amplitude=1.0)
Generate a step signal that transitions from offset
to offset + amplitude
at the specified time.
Step signals are fundamental for system identification, particularly for determining system response characteristics and time constants.
Arguments
N::Int
: Length of the signalstep_time::Real
: Time at which the step occurs (in seconds)Ts::Real=1.0
: Sample time (seconds)offset::Real=0.0
: Initial value of the signal before the stepamplitude::Real=1.0
: Height of the step
Returns
Vector{Float64}
: Step signal
Examples
# Generate a step signal that steps at 5.0 seconds with Ts=0.1
u = step_signal(1000, step_time=5.0, Ts=0.1)
# Generate a step signal with custom offset and amplitude
u = step_signal(1000, step_time=2.5, Ts=0.1, offset=2.0, amplitude=3.0)
Notes
- The signal is
offset
beforestep_time
andoffset + amplitude
afterstep_time
- If step_time ≤ 0, the entire signal is
offset + amplitude
- If step_time is beyond the signal duration, the entire signal is
offset
Example
# Generate step signals
N = 200
Ts = 0.1
u_step1 = step_signal(N; step_time=5.0, Ts) # Step at 5.0 seconds
u_step2 = step_signal(N; step_time=10.0, Ts) # Step at 10.0 seconds
# Plot the signals
p1 = plot(u_step1, title="Step at 5.0 seconds", xlabel="Sample", ylabel="Amplitude",
label="u(t)", linewidth=2)
p2 = plot(u_step2, title="Step at 10.0 seconds", xlabel="Sample", ylabel="Amplitude",
label="u(t)", linewidth=2)
plot(p1, p2, layout=(2,1), size=(600, 400))