nass-simscape/tomo-exp/index.org

9.2 KiB

Tomography Experiment

Initialize Experiment

  initializeGround();
  initializeGranite();
  initializeTy();
  initializeRy();
  initializeRz();
  initializeMicroHexapod();
  initializeAxisc();
  initializeMirror();
  initializeNanoHexapod(struct('actuator', 'piezo'));
  initializeSample(struct('mass', 1));
  t = 0:Ts:Tsim;

Generate perturbations

  win = hanning(ceil(1/Ts));
  [pxx, f] = pwelch(sqrt(1/(2*Ts))*randn(length(t), 1), win, [], [], 1/Ts);
  figure;
  hold on;
  plot(f, sqrt(pxx));
  hold off;
  set(gca, 'xscale', 'log');
  set(gca, 'yscale', 'log');
  xlabel('Frequency [Hz]'); ylabel('ASD of the measured velocity $\left[\frac{m/s}{\sqrt{Hz}}\right]$')
  ylim([0.01, 100]);
  load('./disturbances/mat/dist_psd.mat', 'dist_f');

  Dwx = lsim(dist_f.G_gm, sqrt(1/(2*Ts))*randn(length(t), 1), t);
  Dwy = lsim(dist_f.G_gm, sqrt(1/(2*Ts))*randn(length(t), 1), t);
  Dwz = lsim(dist_f.G_gm, sqrt(1/(2*Ts))*randn(length(t), 1), t);

  Dw = [Dwx, Dwy, Dwz];
  figure;
  hold on;
  plot(t, Dwx);
  plot(t, Dwy);
  plot(t, Dwz);
  hold off;
  xlabel('Time [s]'); ylabel('Displacement [m]');
  Fty_z = lsim(dist_f.G_ty, sqrt(1/(2*Ts))*randn(length(t), 1), t);
  Frz_z = lsim(dist_f.G_rz, sqrt(1/(2*Ts))*randn(length(t), 1), t);
  figure;
  hold on;
  plot(t, Fty_z);
  plot(t, Frz_z);
  hold off;
  xlabel('Time [s]'); ylabel('Force [N]');
  % Spindle
  Rz = 2*pi*t;

  % Axisc
  Rm = zeros(length(t), 2);
  Rm(:, 2) = pi*ones(length(t), 1);

  inputs = struct( ...
      'Ts', Ts,       ...
      'Dw', timeseries(Dw, t), ...
      'Dy', timeseries(zeros(length(t), 1), t), ...
      'Ry', timeseries(zeros(length(t), 1), t), ...
      'Rz', timeseries(Rz, t), ...
      'Dh', timeseries(zeros(length(t), 6), t), ...
      'Rm', timeseries(Rm, t), ...
      'Dn', timeseries(zeros(length(t), 6), t), ...
      'Ds', timeseries(zeros(length(t), 6), t), ...
      'Fg', timeseries(zeros(length(t), 3), t), ...
      'Fn', timeseries(zeros(length(t), 6), t), ...
      'Fnl', timeseries(zeros(length(t), 6), t), ...
      'Fty_x', timeseries(zeros(length(t), 1), t), ...
      'Fty_z', timeseries(Fty_z, t), ...
      'Frz_z', timeseries(Frz_z, t), ...
      'Fs', timeseries(zeros(length(t), 6), t)  ...
  );

Test

  cd ..

We define some parameters:

  • T0 is the duration in seconds
  • N is the number of samples
  T0 = 10; % Signal Duration [s]
  N = 10000; % Number of Samples (should be even)

Then, we have:

  • $f_s = N/T_0$ is the sampling frequency in Hz
  • $f_c = \frac{1}{2} N/T_0$ is the cut-off frequency in Hz
  • $f_0 = 1/T_0$ is the frequency resolution of the DFT in Hz
  Fs = N/T0; % Sampling frequency [Hz]
  Fc = (1/2)*N/T0; % Sampling frequency [Hz]
  df = 1/T0; % Frequency resolution of the DFT [Hz]

We then specify the wanted PSD.

  phi = ones(N/2, 1);
  % phi = logspace(3, 0, N/2);
  phi(df:df:Fs/2>10) = 0;

We create $C_x(k)$ such that: \[ C_x(k) = \sqrt{\Phi_{xx}(k\omega_0)\omega_0} \quad k = 1 \dots N/2 \] where $\Phi_{xx}$ is the wanted PSD.

  C = zeros(N/2, 1);
  for i = 1:N/2
    C(i) = sqrt(phi(i))*2*Fs; % TODO - Why this normalization?
  end

We generate some random phase that will be added to C.

  theta = 2*pi*rand(N/2, 1); % Generate random phase [rad]

In order to have \[ C_x(N/2+i) = C_x^*(N/2-i) \quad i = 1 \dots N/2 \] We do the following

  Cx = [0 ; C.*complex(cos(theta),sin(theta))];
  Cx = [Cx; flipud(conj(Cx(2:end)))];;

The time domain data is generated by an inverse FFT.

  u = ifft(Cx);
  A = fft(u);
  figure; plot(2*A.*conj(A))
  t = linspace(0, T0, N+1); % Time Vector [s]
  figure;
  plot(t, u)
  xlabel('Time [s]');
  ylabel('Amplitude');
  nx = length(u);
  na = 16;
  win = hanning(floor(nx/na));

  [pxx, f] = pwelch(u, win, 0, [], Fs);
  figure;
  hold on;
  plot(f,pxx)
  plot(df:df:Fc,phi)
  hold off;
  xlabel('Frequency [Hz]');
  ylabel('Power Spectral Density');
  set(gca, 'xscale', 'log');
  set(gca, 'yscale', 'log');

Test

  cd ..
  load('./disturbances/mat/dist_psd.mat', 'dist_f');

We remove the first value with very high PSD.

  dist_f.f = dist_f.f(3:end);
  dist_f.psd_gm = dist_f.psd_gm(3:end);

We define some parameters.

  Fs = 2*dist_f.f(end);   % Sampling Frequency of data is twice the maximum frequency of the PSD vector [Hz]
  N = 2*length(dist_f.f); % Number of Samples match the one of the wanted PSD
  T0 = N/Fs;              % Signal Duration [s]
  df = 1/T0;              % Frequency resolution of the DFT [Hz]
                          % Also equal to (dist_f.f(2)-dist_f.f(1))

We then specify the wanted PSD.

  phi = dist_f.psd_gm;

Create amplitudes corresponding to wanted PSD.

  C = zeros(N/2,1);
  for i = 1:N/2
    C(i) = sqrt(phi(i)*df);
  end

Add random phase to C.

  theta = 2*pi*rand(N/2,1); % Generate random phase [rad]

  Cx = [0 ; C.*complex(cos(theta),sin(theta))];
  Cx = [Cx; flipud(conj(Cx(2:end)))];;

The time domain data is generated by an inverse FFT. We normalize the ifft Matlab command.

  u = 1/(sqrt(2)*df*1/Fs)*ifft(Cx); % Normalisation of the IFFT
  t = linspace(0, T0, N+1); % Time Vector [s]
  figure;
  plot(t, u)
  xlabel('Time [s]');
  ylabel('Amplitude');
  u_rep = [u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u;u];
  nx = length(u_rep);
  na = 16;
  win = hanning(floor(nx/na));

  [pxx, f] = pwelch(u_rep, win, 0, [], Fs);
  figure;
  hold on;
  plot(dist_f.f, dist_f.psd_gm, 'DisplayName', 'Original PSD')
  plot(f, pxx, 'DisplayName', 'Computed')
  % plot(f, pxx./dist_f.psd_gm, 'k-')
  hold off;
  xlabel('Frequency [Hz]');
  ylabel('Power Spectral Density');
  set(gca, 'xscale', 'log'); set(gca, 'yscale', 'log');
  legend('location', 'northeast');