# FUNZIONE: Bodeplot
ggbodeplot <- function(tf, fmin=1, fmax=1e4, df=0.01) {
# vector of points for each order of magnitude (OOM):
pts <- 10^seq(0, 1, df) %>% tail(-1)
# vector of OOMs:
ooms <- 10^(floor(log10(fmin)):ceiling(log10(fmax)-1))
# combine pts and ooms:
freqs <- as.vector(pts %o% ooms)
# warning: bode wants pulsation!
bode(tf, freqs*2*pi) %>% {
tibble(f=.$w/(2*pi), `magnitude (dB)`=.$mag, `phase (deg)`=.$phase)} %>%
pivot_longer(-f) %>%
ggplot(aes(x=f, y=value)) +
geom_line() +
scale_x_log10(
minor_breaks=scales::minor_breaks_n(10),
labels= ~ latex2exp::TeX(paste0("$10^{", log10(.), "}$"))) +
facet_wrap(~name, nrow=2, scales="free") +
labs(x="frequency (Hz)")
}
# FUNZIONE: Generazione segnale sinusoidale con diverse armoniche
signal <- function(t, pars, rad = FALSE) {
stopifnot(is.data.frame(pars))
with(pars, {
if (!rad) {
phi <- phi/180*pi
f <- 2*pi*f
}
map_dbl(t, \(t) sum( map_vec(seq_along(w) , \(i) w[i]*cos(t*f[i] + phi[i] ))))
})
}4. Inversione delle armoniche pure (DARE)
Questo esercizio genera delle armoniche pure in ingresso ad un sistema di isolamento delle vibrazioni, simulazione dell’uscita e—mediante inversione della dinamica—stimare quella originaria in ingresso.
1 Parte fornita per l’esercitazione
1.1 Funzioni
1.2 Segnale in ingresso
Definiamo un segnale d’ingresso (nel caso di sistemi di misura si tratta di un misurando) costituito da segnali armonici, più un eventuale disturbo normale:
f0 <- 10
# Provare con un'armonica pura
# pars <- tibble(
# w = c(1),
# f = c(f0), # 1 funziona
# phi = c(0)
# )
# Provare con tante armoniche
pars <- tibble(
w = c(1, 0.1, 0.3),
f = c(15, 20, 45),
phi = c(0, 0, 0)
)
Nt <- 1000 # numero totale dei campioni
s <- tibble(
t = 0:Nt * 0.001, # 1 kHz di frequenza di campionamento
u = signal(t, pars),
un = u + rnorm(length(t), 0, pars$w[1] / 10)
)La trasformata di Fourier mostra i picchi attesi:
s %>%
mutate(
f = 0:(n()-1)/max(t),
fft_u = fft(un),
intensity_u = Mod(fft_u) / n()*2,
phase_u = Arg(fft_u)/pi*180
) %>%
slice_head(n=as.integer(nrow(.)/2)) %>%
ggplot(aes(x=f, y=intensity_u)) +
geom_spoke(aes(y=0, radius=intensity_u, angle=pi/2)) +
geom_point()
1.3 Impieghiamo un sistema per isolamento da vibrazioni per simulare l’uscita
Con il metodo delle impedenze generalizzate si ottiene:
\[ H(i\omega)=\frac{V_\mathrm{out}(i\omega)}{V_\mathrm{in}(i\omega)}=\frac{C i\omega + K}{M (i\omega)^2 + C i\omega + K} \tag{1}\]
La frequenza naturale del sistema è \(f_0=\frac{1}{2\pi}\sqrt{\frac{K}{M}}\), e l’attenuazione comincia a \(\sqrt{2}f_0\).
Possiamo definire la funzione di trasferimento in Equazione 1 con la funzione control::tf(), che prende come due argomenti due vettori con i coefficienti della Equazione 1, in ordine decrescente di grado della variabile \(i\omega\):
M <- 10
K <- 1000
C <- 50
# Frequenza naturale:
fn <- 1/(2*pi) * sqrt(K/M)
num <- c(C, K)
den <- c(M, C, K)
H <- tf(num, den)
ggbodeplot(H, fmin=0.1, fmax=100) +
geom_vline(xintercept=c(1, sqrt(2)) * fn, color="red", linetype=2) +
labs(title=paste(
"Natural frequency:", round(fn, 2), "Hz",
" - Isolation: >", round(sqrt(2)*fn, 2), "Hz"))Registered S3 methods overwritten by 'signal':
method from
print.freqs gsignal
print.freqz gsignal
print.grpdelay gsignal
plot.grpdelay gsignal
print.impz gsignal
print.specgram gsignal
plot.specgram gsignal

cat("Per la frequenza", f0, "Hz abbiamo: \nModulo:", Mod(freqresp(H, 2*pi*f0)), "\nFase:", Arg(freqresp(H, 2*pi*f0))*180/pi, "°\n")Per la frequenza 10 Hz abbiamo:
Modulo: 0.08539786
Fase: -102.9892 °
O anche, usando glue, è più semplice comporre delle stringe inserendo tra graffe le espressioni da valutare:
glue("Per la frequenza {f0} Hz abbiamo: \nModulo: {Mod(freqresp(H, 2*pi*f0)) %>% round(3)}\nFase: {(Arg(freqresp(H, 2*pi*f0))*180/pi) %>% round(3)}°")Per la frequenza 10 Hz abbiamo:
Modulo: 0.085
Fase: -102.989°
Dunque, se inseriamo un’armonica a fase nulla come un coseno \(\cos(\omega_{0} t)\) di frequenza pari a 10 Hz avremo in uscita la stessa armonica attenuata di 0.085 e sfasata di 103°. Dovrebbe comportarsi effettivamente come un sistema di isolamento delle vibrazioni.
1.4 Simulazione uscita
Andiamo a verificarlo. Simuliamo cosa succede in uscita se imponiamo il segnale al sistema d’isolamento impiegando il simulatore integrato in R lsim().
output <- lsim(H, s$un, s$t)
s <- s %>%
mutate(
# Simulazione dell'uscita
y = output$y[1,]
)
# Grafici
pp <- plot_ly() %>%
add_lines(s$t, s$y, name = "output", line= list(color= "red")) %>%
add_lines(s$t, s$un, name = "input", line= list(color= "blue")) %>%
layout(title = "Input & Output")
ppAttenzione: i grafici che usano plotly sono oggetti Javascript e in quanto tali non sono compatibili con LaTeX, quindi non è possibile generare anche la versione pdf se il documento contiene grafici plotly.
(s %>%
select(t, input=y, output=un) %>%
pivot_longer(-t, names_to = "segnale", values_to = "valore") %>%
ggplot(aes(x=t, y=valore, color=segnale)) +
geom_line()) %>%
ggplotly()Se avete usato come parametro frequenza della funzione creata 10 Hz potete verificare come il segnale in uscita si sia effettivamente attenuato di parecchio!
Riconoscimento punti esame
Il completamento di questo esercizio comporta il riconoscmiento di ±1 punto.
Da fare
Stimare il segnale in ingresso originale a partire dal segnale in uscita e dal modulo e la fase della funzione di trasferimento
NOTA: impiegare funzioni che processano automaticamente tutte le armoniche che sono presenti nel segnale. In altre parole impiegare nelle funzioni che costruirete la struttura della funzione signal()
Suggerimenti
- calcolare FFT
- trovare i picchi FFT
- applicare inversa di modulo e fase della funz trasferimento alle armoniche corrispondenti ai picchi del modulo della FFT
- scrivere una funzione che stima l’ingresso da generiche componenti armoniche in uscita che avrete salvato in un contenitore dati ‘picchi’ ed H(w):
signal_input <- function(t, picchi, H) {} - quando il vostro codice funziona provate ad aggiungere altre armoniche
- quando il vostro codice funziona provate ad aggiungere rumore