diff --git a/dcm_lookup_tables.org b/dcm_lookup_tables.org index 4deba08..de0b8da 100644 --- a/dcm_lookup_tables.org +++ b/dcm_lookup_tables.org @@ -52,43 +52,18 @@ * Introduction :ignore: -Several Lookup Tables (LUT) are used for the DCM in order to compensate for *repeatable* errors. -- Section [[sec:dcm_stepper_lut]]: the stepper motors are calibrated using interferometers. -- Section [[sec:dcm_attocube_lut]]: the Attocube periodic non-linearities are calibrated using piezoelectric actuators. +A Fast Jack is composed of one stepper motor and a piezoelectric stack in series. -* Stepper Motors -:PROPERTIES: -:header-args:matlab+: :tangle matlab/dcm_stepper_lut.m -:END: -<> -** Introduction :ignore: -Fast jack coarse displacement is performed with a Stepper motor and a ball screw mechanism. -Such positioning system has some repeatable motion errors than can be calibrated using a measurement system having less errors. +The stepper motor is directly driving (i.e. without a reducer) a ball screw with a pitch of 1mm (i.e. 1 stepper motor turn makes a 1mm linear motion). -For the DCM, this can be done using the interferometers. +The stepper motor is doing the coarse displacement while the piezoelectric stack is only there to compensate all the motion errors of the stepper motor. -** Matlab Init :noexport:ignore: -#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) -<> -#+end_src +A Lookup Tables (LUT) is used to compensate for *repeatable* errors of the stepper motors. +This has several goals: +- Reduce errors down to the stroke of the piezoelectric stack actuator +- Reduce errors above the bandwidth of the feedback controller -#+begin_src matlab :exports none :results silent :noweb yes -<> -#+end_src - -#+begin_src matlab :tangle no :noweb yes -<> -#+end_src - -#+begin_src matlab :eval no :noweb yes -<> -#+end_src - -#+begin_src matlab :noweb yes -<> -#+end_src - -** Schematic +* Schematic In order to measure the errors induced by the fast jacks, we have to make some scans, and measure simultaneously: - The wanted fast jack position: signal/step sent by the IcePAP @@ -171,7 +146,27 @@ The measured motion of the fast jacks $[d_{u_r},\ r_{u_h},\ r_d]$ can be compare #+RESULTS: [[file:figs/block_diagram_lut_stepper.png]] -** TODO [#A] Repeatability of the motion :noexport: +* First Analysis +** Matlab Init :noexport:ignore: +#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) +<> +#+end_src + +#+begin_src matlab :exports none :results silent :noweb yes +<> +#+end_src + +#+begin_src matlab :tangle no :noweb yes +<> +#+end_src + +#+begin_src matlab :eval no :noweb yes +<> +#+end_src + +#+begin_src matlab :noweb yes +<> +#+end_src ** Patterns in the Fast Jack motion errors In order to understand what should be the "sampling distance" for the lookup table of the stepper motor, we have to analyze the displacement errors induced by the stepper motor. @@ -667,7 +662,7 @@ exportFig('figs/compare_old_new_lut_motion.pdf', 'width', 'wide', 'height', 'nor #+RESULTS: [[file:figs/compare_old_new_lut_motion.png]] -** Experimental Data - Proposed method +** Experimental Data - Proposed method (BLISS first implementation) The new proposed method has been implemented and tested. The result is shown in Figure [[fig:lut_comp_old_new_experiment]]. @@ -728,7 +723,7 @@ exportFig('figs/lut_comp_old_new_experiment_zoom.pdf', 'width', 'wide', 'height' #+end_src #+name: fig:lut_comp_old_new_experiment_zoom -#+caption: +#+caption: Comparison of the residual motion after old LUT and new LUT #+RESULTS: [[file:figs/lut_comp_old_new_experiment_zoom.png]] @@ -883,73 +878,13 @@ exportFig('figs/effect_lut_on_cps_error_spatial.pdf', 'width', 'wide', 'height', #+RESULTS: [[file:figs/effect_lut_on_cps_error_spatial.png]] -* Metrology Frame Deformations -* Attocube Periodic Non-Linearity -:PROPERTIES: -:header-args:matlab+: :tangle matlab/dcm_attocube_lut.m -:END: -<> +* LUT creation from experimental data ** Introduction :ignore: +In this section, the full process from measurement, filtering of data to generation of the LUT is detailed. -The idea is to calibrate the periodic non-linearity of the interferometers, a known displacement must be imposed and the interferometer output compared to this displacement. -This should be performed over several periods in order to characterize the error. +The computation is performed with Matlab. -We here suppose that we are already in the frame of the Attocube (the fast-jack displacements are converted to Attocube displacement using the transformation matrices). -We also suppose that we are at a certain Bragg angle, and that the stepper motors are not moving: only the piezoelectric actuators are used. - -The setup is schematically with the block diagram in Figure [[fig:block_diagram_lut_attocube]]. -The signals are: -- $u$: Actuator Signal (position where we wish to go) -- $d$: Disturbances affecting the signal -- $y$: Displacement of the crystal -- $y_g$: Measurement of the crystal motion by the strain gauge with some noise $n_g$ -- $y_a$: Measurement of the crystal motion by the interferometer with some noise $n_a$ - -#+begin_src latex :file block_diagram_lut_attocube.pdf -\definecolor{myblue}{rgb}{0, 0.447, 0.741} -\definecolor{myred}{rgb}{0.8500, 0.325, 0.098} - -\begin{tikzpicture} - \node[block] (G) at (0,0){$G(s)$}; - \node[addb, right=1 of G] (addd) {}; - \node[block, align=center, right=1 of addd] (non_linearity) {Periodic\\Non-linearity}; - \node[addb, right=1 of non_linearity] (addna) {}; - \node[addb, below=1.8 of addna] (addnsg) {}; - - \draw[->] ($(G.west) + (-1.0, 0)$) node[above right]{$u$} -- (G.west); - \draw[->] (G.east) -- (addd.west); - \draw[->] (addd.east) -- (non_linearity.west); - \draw[->] ($(addd.north) + (0, 1.0)$) node[below right]{$d$} -- (addd.north); - \draw[->] (non_linearity.east) -- (addna.west); - \draw[->] (addna.east) -- ++(1.2, 0) node[above left]{$y_a$}; - \draw[->] ($(addna.north) + (0, 1.0)$) node[below right](na){$n_a$} -- (addna.north); - \draw[->] ($(addd.east) + (0.4, 0)$)node[branch]{} node[above]{$y$} |- (addnsg.west); - \draw[->] (addnsg.east) -- ++(1.2, 0) node[above left]{$y_g$}; - \draw[->] ($(addnsg.north) + (0, 1.0)$) node[below right](nsg){$n_{g}$} -- (addnsg.north); - - \begin{scope}[on background layer] - \node[fit={(non_linearity.south west) (na.north east)}, fill=myblue!20!white, draw, inner sep=6pt] (attocube) {}; - \node[fit={(non_linearity.west|-addnsg.south) (nsg.north east)}, fill=myred!20!white, draw, inner sep=6pt] (straingauge) {}; - \node[below right] at (attocube.north west) {Attocube}; - \node[below right] at (straingauge.north west) {Strain Gauge}; - \end{scope} -\end{tikzpicture} -#+end_src - -#+name: fig:block_diagram_lut_attocube -#+caption: Block Diagram schematic of the setup used to measure the periodic non-linearity of the Attocube -#+RESULTS: -[[file:figs/block_diagram_lut_attocube.png]] - -The problem is to estimate the periodic non-linearity of the Attocube from the imperfect measurments $y_a$ and $y_g$. - -Then a Lookup Table (LUT) is build. - -The wavelength of the Attocube is 1530nm, therefore the non-linearity has a period of 765nm. -The amplitude of the non-linearity can vary from one unit to the other (and maybe from one experimental condition to the other). -It is typically between 5nm peak to peak and 20nm peak to peak. - -** Matlab Init :noexport:ignore: +** Matlab Init :noexport:ignore: #+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) <> #+end_src @@ -970,22 +905,2356 @@ It is typically between 5nm peak to peak and 20nm peak to peak. <> #+end_src +** Load Data +A Bragg scan is performed using =thtraj= and data are acquired using the =fast_DAQ=. +#+begin_src matlab +%% Load Raw Data +load("scan_10_70_lut_1.mat") +#+end_src + +Measured data are: +- =bragg=: Bragg angle in deg +- =dz=: distance between crystals in nm +- =dry=, =drx=: orientation errors between crystals in nrad +- =fjur=, =fjuh=, =fjd=: generated steps by the IcePAP in tens of nm + +All are sampled at 10kHz with no filtering. + +First, convert all the data to SI units (rad, and m). +#+begin_src matlab +%% Convert Data to Standard Units +% Bragg Angle [rad] +bragg = pi/180*bragg; +% Rx rotation of 1st crystal w.r.t. 2nd crystal [rad] +drx = 1e-9*drx; +% Ry rotation of 1st crystal w.r.t. 2nd crystal [rad] +dry = 1e-9*dry; +% Z distance between crystals [m] +dz = 1e-9*dz; +% Z error between second crystal and first crystal [m] +ddz = 10.5e-3./(2*cos(bragg)) - dz; +% Steps for Ur motor [m] +fjur = 1e-8*fjur; +% Steps for Uh motor [m] +fjuh = 1e-8*fjuh; +% Steps for D motor [m] +fjd = 1e-8*fjd; +#+end_src + +** IcePAP generated Steps +Here is how the steps of the IcePAP (=fjsur=, =fjsuh= and =fjsd=) are computed in mode A: +\begin{equation} +\begin{bmatrix} +\text{fjsur} \\ +\text{fjsuh} \\ +\text{fjsd} +\end{bmatrix} (\theta) = \text{fjs}_0 + +\bm{J}_{a,111} \cdot \begin{bmatrix} +0 \\ +\text{fjsry} \\ +\text{fjsrx} +\end{bmatrix} - \frac{10.5 \cdot 10^{-3}}{2 \cos (\theta)} +\end{equation} + +There is a first offset $\text{fjs}_0$ that is initialized once, and a second offset which is a function of =fjsry= and =fjsrx=. + +Let's compute the offset which is a function of =fjsry= and =fjsrx=: +#+begin_src matlab +fjsry = 0.53171e-3; % [rad] +fjsrx = 0.144e-3; % [rad] + +J_a_111 = [1, 0.14, -0.0675 + 1, 0.14, 0.1525 + 1, -0.14, 0.0425]; + +fjs_offset = J_a_111*[0; fjsry; fjsrx]; % ur,uh,d offsets [m] +#+end_src + +#+begin_src matlab :results value replace :exports results :tangle no +ans = fjs_offset +#+end_src + +#+RESULTS: +| 6.4719e-05 | +| 9.6399e-05 | +| -6.8319e-05 | + +Let's now compute $\text{fjs}_0$ using first second of data where there is no movement and bragg axis is fixed at $\theta_0$: +\begin{equation} +\text{fjs}_0 = \begin{bmatrix} +\text{fjsur} \\ +\text{fjsuh} \\ +\text{fjsd} +\end{bmatrix} (\theta_0) + \frac{10.5 \cdot 10^{-3}}{2 \cos (\theta_0)} - +\bm{J}_{a,111} \cdot \begin{bmatrix} +0 \\ +\text{fjsry} \\ +\text{fjsrx} +\end{bmatrix} +\end{equation} + +#+begin_src matlab +FJ0 = ... + mean([fjur(time < 1), fjuh(time < 1), fjd(time < 1)])' ... + + ones(3,1)*10.5e-3./(2*cos(mean(bragg(time < 1)))) ... + - fjs_offset; % [m] +#+end_src + +#+begin_src matlab :results value replace :exports results :tangle no +ans = FJ0 +#+end_src + +#+RESULTS: +| 0.030427 | +| 0.030427 | +| 0.030427 | + +Values are very close for all three axis. +Therefore we take the mean of the three values for $\text{fjs}_0$. +#+begin_src matlab +FJ0 = mean(FJ0); +#+end_src + +This approximately corresponds to the distance between the crystals for a Bragg angle of 80 degrees: +#+begin_src matlab :results value replace :exports both :tangle no +10.5e-3/(2*cos(80*pi/180)) +#+end_src + +#+RESULTS: +: 0.030234 + +The measured IcePAP steps are compared with the theoretical formulas in Figure [[fig:step_lut_estimation_wanted_fj_pos]]. + +If we were to zoom a lot, we would see a small delay between the estimation and the steps sent by the IcePAP. +This is due to the fact that the estimation is performed based on the measured Bragg angle while the IcePAP steps are based on the "requested" Bragg angle. +As will be shown in the next section, there is a small delay between the requested and obtained bragg angle which explains this delay. + +#+begin_src matlab :exports none +%% +figure; +hold on; +plot(time, 1e3*fjur, 'DisplayName', '$u_r$') +plot(time, 1e3*fjuh, 'DisplayName', '$u_h$') +plot(time, 1e3*fjd , 'DisplayName', '$d$') +set(gca,'ColorOrderIndex',1) +plot(time, 1e3*(FJ0 + fjs_offset(1) - 10.5e-3./(2*cos(bragg))), 'k--', ... + 'DisplayName', 'Estimation') +plot(time, 1e3*(FJ0 + fjs_offset(2) - 10.5e-3./(2*cos(bragg))), 'k--', ... + 'HandleVisibility', 'off') +plot(time, 1e3*(FJ0 + fjs_offset(3) - 10.5e-3./(2*cos(bragg))), 'k--', ... + 'HandleVisibility', 'off') +xlabel('Bragg Angle [deg]'); ylabel('Fast Jack Pos [mm]'); +xlim([64.2, 65.2]); +legend('location', 'northeast'); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_estimation_wanted_fj_pos.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:step_lut_estimation_wanted_fj_pos +#+caption: Measured IcePAP Steps and estimation from theoretical formula +#+RESULTS: +[[file:figs/step_lut_estimation_wanted_fj_pos.png]] + +** Bragg and Fast Jack Velocities +In order to estimate velocities from measured positions, a filter is used which approximate a pure derivative filter. + +#+begin_src matlab +%% Filter to compute velocities +G_diff = (s/2/pi/10)/(1 + s/2/pi/10); +% Make sure the gain w = 2pi is equal to 2pi +G_diff = 2*pi*G_diff/(abs(evalfr(G_diff, 1j*2*pi))); +#+end_src + +Only the high frequency amplitude is reduced to not amplified the measurement noise (Figure [[fig:step_lut_deriv_filter]]). + +#+begin_src matlab :exports none +%% Bode Plot of the Gdiff filter and comparison with pure derivative filter +freqs = logspace(-1,3,1000); +figure; +hold on; +plot(freqs, abs(squeeze(freqresp(G_diff, freqs, 'Hz'))), ... + 'DisplayName', '$G_d$'); +plot(freqs, abs(squeeze(freqresp(s, freqs, 'Hz'))), ... + 'DisplayName', '$s$'); +hold off; +set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); +xlabel('Frequency [Hz]'); ylabel('Amplitude [m/N]'); +legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 2); +xlim([-1, 1e3]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_deriv_filter.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:step_lut_deriv_filter +#+caption: Magnitude of filter used to approximate the derivative +#+RESULTS: +[[file:figs/step_lut_deriv_filter.png]] -** Simulations -We have some constrains on the way the motion is imposed and measured: -- We want the frequency content of the imposed motion to be at low frequency in order not to induce vibrations of the structure. - We have to make sure the forces applied by the piezoelectric actuator only moves the crystal and not the fast jack below. - Therefore, we have to move much slower than the first resonance frequency in the system. -- As both $y_a$ and $y_g$ should have rather small noise, we have to filter them with low pass filters. - The cut-off frequency of the low pass filter should be high as compared to the motion (to not induce any distortion) but still reducing sufficiently the noise. - Let's say we want the noise to be less than 1nm ($6 \sigma$). +Using the filter, the Bragg velocity is estimated (Figure [[fig:step_lut_bragg_vel]]). +#+begin_src matlab +%% Bragg Velocity +bragg_vel = lsim(G_diff, bragg, time); +#+end_src -Suppose we have the power spectral density (PSD) of both $n_a$ and $n_g$. +#+begin_src matlab :exports none +%% Plot of Bragg Velocity +figure; +hold on; +plot(time(time > 1), 180/pi*bragg_vel(time > 1)) +hold off; +xlabel('Time [s]'); ylabel('Bragg Velocity [deg/s]'); +xlim([2, 4]); +#+end_src -- [ ] Take the PSD of the Attocube -- [ ] Take the PSD of the strain gauge -- [ ] Using 2nd order low pass filter, estimate the required low pass filter cut-off frequency to have sufficiently low noise +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_bragg_vel.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:step_lut_bragg_vel +#+caption: Estimated Bragg Velocity curing acceleration phase +#+RESULTS: +[[file:figs/step_lut_bragg_vel.png]] + + +Now, the Fast Jack velocity is estimated (Figure [[fig:step_lut_fast_jack_vel]]). +#+begin_src matlab +%% Fast Jack Velocity +fjur_vel = lsim(G_diff, fjur, time); +fjuh_vel = lsim(G_diff, fjuh, time); +fjd_vel = lsim(G_diff, fjd , time); +#+end_src + +#+begin_src matlab :exports none +%% Plot of Fast Jack Velocity +figure; +hold on; +plot(time(time > 1), 1e3*fjur_vel(time > 1), ... + 'DisplayName', '$u_r$') +plot(time(time > 1), 1e3*fjuh_vel(time > 1), ... + 'DisplayName', '$u_h$') +plot(time(time > 1), 1e3*fjd_vel( time > 1), ... + 'DisplayName', '$d$') +hold off; +xlabel('Time [s]'); ylabel('Fast Jack Velocity [mm/s]'); +legend('location', 'southwest'); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_fast_jack_vel.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:step_lut_fast_jack_vel +#+caption: Estimated velocity of fast jacks +#+RESULTS: +[[file:figs/step_lut_fast_jack_vel.png]] + +#+begin_src matlab :exports none +%% Plot of Fast Jack Velocity +figure; +hold on; +plot(1e3*fjur(time > 1), 1e3*fjur_vel(time > 1), ... + 'DisplayName', '$u_r$') +plot(1e3*fjuh(time > 1), 1e3*fjuh_vel(time > 1), ... + 'DisplayName', '$u_h$') +plot(1e3*fjd(time > 1), 1e3*fjd_vel( time > 1), ... + 'DisplayName', '$d$') +hold off; +xlabel('Fast Jack Position [mm]'); ylabel('Fast Jack Velocity [mm/s]'); +legend('location', 'southeast'); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_fast_jack_vel_fct_pos.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:step_lut_fast_jack_vel_fct_pos +#+caption: Fast Jack Velocity as a function of its position +#+RESULTS: +[[file:figs/step_lut_fast_jack_vel_fct_pos.png]] + +** Bragg Angle Errors / Delays + +From the measured =fjur= steps generated by the IcePAP, we can estimate the steps generated corresponding to the Bragg angle. +#+begin_src matlab +%% Estimated Bragg angle requested by IcePAP +bragg_icepap = acos(10.5e-3./(2*(FJ0 + fjs_offset(1) - fjur))); +#+end_src + +The generated steps by the IcePAP and the measured angle are compared in Figure [[fig:lut_step_bragg_angle_error_aerotech]]. +There is clearly a lag of the Bragg angle compared to the generated IcePAP steps. +#+begin_src matlab :exports none +%% Error Between generated Bragg steps and measured angle +figure; +hold on; +plot(time, 180/pi*bragg_icepap, ... + 'DisplayName', 'IcePAP Steps') +plot(time, 180/pi*bragg, ... + 'DisplayName', 'Encoder Measurement') +hold off; +xlabel('Time [s]'); ylabel('Bragg Angle [deg]'); +xlim([3.18, 3.19]); +legend('location', 'southeast'); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/lut_step_bragg_angle_error_aerotech.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:lut_step_bragg_angle_error_aerotech +#+caption: Estimated generated steps by the IcePAP and measured Bragg angle +#+RESULTS: +[[file:figs/lut_step_bragg_angle_error_aerotech.png]] + + +#+begin_src matlab :exprts none +% Take only deceleration portion +scan_i = time > 60 & time < 65.1; +#+end_src + +If we plot the error between the measured and the requested bragg angle as a function of the bragg velocity (Figure [[fig:lut_step_bragg_error_fct_velocity]]), we can see an almost linear relationship. + +This corresponds to a "time lag" of approximately: +#+begin_src matlab :results value replace :exports results :tangle no +sprintf('%.1f ms', 1e3*(bragg_vel(scan_i)\(bragg_icepap(scan_i) - bragg(scan_i)))) +#+end_src + +#+RESULTS: +: 2.4 ms + +#+begin_src matlab :exports none +%% Bragg Error as a function fo the Bragg Velocity +figure; +plot(180/pi*bragg_vel(scan_i), 180/pi*bragg_icepap(scan_i) - 180/pi*bragg(scan_i), 'k.') +xlabel('Bragg Velocity [deg/s]'); ylabel('Bragg Error [deg]') +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/lut_step_bragg_error_fct_velocity.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:lut_step_bragg_error_fct_velocity +#+caption: Bragg Error as a function fo the Bragg Velocity +#+RESULTS: +[[file:figs/lut_step_bragg_error_fct_velocity.png]] + +#+begin_important +There is a "lag" between the Bragg steps sent by the IcePAP and the measured angle by the encoders. +This is probably due to the single integrator in the "Aerotech" controller. +Indeed, two integrators are required to have no tracking error during ramp reference signals. +#+end_important + +** Errors in the Frame of the Crystals + +The =dz=, =dry= and =drx= measured relative motion of the crystals are defined as follows: +- An increase of =dz= means the crystals are moving away from each other +- An positive =dry= means the second crystals has positive rotation around =y= +- An positive =drx= means the second crystals has positive rotation around =x= + +The error in crystals' distance =ddz= is defined as: +\begin{equation} +ddz(\theta) = \frac{10.5 \cdot 10^{-3}}{2 \cos(\theta)} - dz(\theta) +\end{equation} + +Therefore, a positive =ddz= means that the second crystal is too high (fast jacks have to move down). + +The errors measured in the frame of the crystals are shown in Figure [[fig:lut_step_measured_errors]]. + +#+begin_src matlab :exports none +%% Open Loop Errors of the Fast Jacks +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(1e3*fjur, 1e6*dry, ... + 'DisplayName', '$dry$'); +plot(1e3*fjur, 1e6*drx, ... + 'DisplayName', '$drx$'); +hold off; +ylabel('Orientation Errors [$\mu$rad]'); +xlabel('Fast Jack Position [mm]'); +legend('location', 'northeast'); + +ax2 = nexttile(); +plot(1e3*fjur, 1e6*ddz, ... + 'DisplayName', '$dz$'); +ylabel('Distance Errors [$\mu$m]'); +xlabel('Fast Jack Position [mm]'); +legend('location', 'northeast'); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/lut_step_measured_errors.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:lut_step_measured_errors +#+caption: Measured errors in the frame of the crystals as a function of the fast jack position +#+RESULTS: +[[file:figs/lut_step_measured_errors.png]] + +** Errors in the Frame of the Fast Jacks + +From =ddz,dry,drx=, the motion errors of the jast-jacks (=fjur_e=, =fjuh_e= and =jfd_e=) as measured by the interferometers are computed. +#+begin_src matlab +%% Actuator Jacobian +J_a_111 = [1, 0.14, -0.0675 + 1, 0.14, 0.1525 + 1, -0.14, 0.0425]; + +%% Computation of the position of the FJ as measured by the interferometers +error = J_a_111 * [ddz, dry, drx]'; + +fjur_e = error(1,:)'; % [m] +fjuh_e = error(2,:)'; % [m] +fjd_e = error(3,:)'; % [m] +#+end_src + +The result is shown in Figure [[fig:lut_step_measured_error_fj]]. + +#+begin_src matlab :exports none +%% Plot of the errors in the Frame of the Fast Jacks +figure; +hold on; +plot(1e3*fjur, 1e6*fjur_e, ... + 'DisplayName', '$u_r$'); +plot(1e3*fjuh, 1e6*fjuh_e, ... + 'DisplayName', '$u_h$'); +plot(1e3*fjd, 1e6*fjd_e, ... + 'DisplayName', '$d$'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Position Error [$\mu$m]'); +legend('location', 'northeast', 'FontSize', 8); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/lut_step_measured_error_fj.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:lut_step_measured_error_fj +#+caption: Position error of the Fast jacks +#+RESULTS: +[[file:figs/lut_step_measured_error_fj.png]] + +#+begin_src matlab :exports none +%% Plot of the measured position of the FJ as a function of their wanted positions +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(1e3*fjur, 1e6*fjur_e, ... + 'DisplayName', '$u_r$'); +plot(1e3*fjuh, 1e6*fjuh_e, ... + 'DisplayName', '$u_h$'); +plot(1e3*fjd, 1e6*fjd_e, ... + 'DisplayName', '$d$'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Position Error [$\mu$m]'); +legend('location', 'southeast', 'FontSize', 8); +axis square; +xlim([14.99, 15.01]); + +ax2 = nexttile(); +hold on; +plot(1e3*fjur, 1e6*fjur_e, ... + 'DisplayName', '$u_r$'); +plot(1e3*fjuh, 1e6*fjuh_e, ... + 'DisplayName', '$u_h$'); +plot(1e3*fjd, 1e6*fjd_e, ... + 'DisplayName', '$d$'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Measured Position [$\mu$m]'); +legend('location', 'southeast', 'FontSize', 8); +axis square; +xlim([19.99, 20.01]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/lut_step_measured_error_fj_zoom.pdf', 'width', 'full', 'height', 'tall'); +#+end_src + +#+name: fig:lut_step_measured_error_fj_zoom +#+caption: Position error of the Fast jacks - Zoom near two positions +#+RESULTS: +[[file:figs/lut_step_measured_error_fj_zoom.png]] + +** Analysis of the obtained error +The measured position of the fast jacks are displayed as a function of the IcePAP steps (Figure [[fig:lut_step_meas_pos_fct_wanted_pos]]). + +#+begin_important +From Figure [[fig:lut_step_meas_pos_fct_wanted_pos]], it seems the position as a function of the IcePAP steps is not a bijection function. +Therefore, a measured position can corresponds to several IcePAP Steps. +This is very problematic for building a LUT that will be used to compensated the measured errors. +#+end_important + +Also, it seems that the (spatial) period of the error depends on the actual position of the Fast Jack (and therefore of its velocity). +If we compute the equivalent temporal period, we find a frequency of around 370 Hz. + +#+begin_src matlab :exports none +%% Plot of the measured position of the FJ as a function of their wanted positions +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(1e3*fjur, 1e3*(fjur + fjur_e), ... + 'DisplayName', '$u_r$'); +plot(1e3*fjuh, 1e3*(fjuh + fjuh_e), ... + 'DisplayName', '$u_h$'); +plot(1e3*fjd, 1e3*(fjd + fjd_e), ... + 'DisplayName', '$d$'); +plot(1e3*fjd, 1e3*fjd, 'k--', ... + 'DisplayName', 'Ref'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Measured Position [mm]'); +legend('location', 'southeast', 'FontSize', 8); +axis square; +xlim([14.99, 15.01]); ylim([14.99, 15.01]); +xticks([14.99 14.995 15 15.005 15.01]); +yticks([14.99 14.995 15 15.005 15.01]); +xtickangle(45); +ytickangle(90); + +ax2 = nexttile(); +hold on; +plot(1e3*fjur, 1e3*(fjur + fjur_e), ... + 'DisplayName', '$u_r$'); +plot(1e3*fjuh, 1e3*(fjuh + fjuh_e), ... + 'DisplayName', '$u_h$'); +plot(1e3*fjd, 1e3*(fjd + fjd_e), ... + 'DisplayName', '$d$'); +plot(1e3*fjd, 1e3*fjd, 'k--', ... + 'DisplayName', 'Ref'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Measured Position [mm]'); +legend('location', 'southeast', 'FontSize', 8); +axis square; +xlim([19.99, 20.01]); ylim([19.99, 20.01]); +xticks([19.99 19.995 20 20.005 20.01]); +yticks([19.99 19.995 20 20.005 20.01]); +xtickangle(45); +ytickangle(90); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/lut_step_meas_pos_fct_wanted_pos.pdf', 'width', 'full', 'height', 'tall'); +#+end_src + +#+name: fig:lut_step_meas_pos_fct_wanted_pos +#+caption: Measured Fast Jack position as a function of the IcePAP steps +#+RESULTS: +[[file:figs/lut_step_meas_pos_fct_wanted_pos.png]] + +In order to better investigate what is going on, a spectrogram is computed (Figure [[fig:lut_step_meas_pos_error_spectrogram]]). + +We clearly observe: +- Some rather constant vibrations with a frequency at around 363Hz and 374Hz. + This corresponds to the clear periods in Figure [[fig:lut_step_meas_pos_fct_wanted_pos]]. + These are due to the =mcoil= stepper motor (magnetic period). +- Several frequencies which are increasing with time. + These corresponds to (spatial) periodic errors of the stepper motor. + The frequency of these errors are increasing because the velocity of the fast jack is also increasing with time (see Figure [[fig:step_lut_fast_jack_vel]]). + The black dashed line in Figure [[fig:lut_step_meas_pos_error_spectrogram]] shows the frequency of errors with a period of $5\,\mu m$. + We can also see lower frequencies corresponding to periods of $10\,\mu m$ and $20\,\mu m$ and lots of higher frequencies with are also exciting resonances of the system (second crystal) at around 200Hz + +#+begin_src matlab :exports none +%% Spectrogram +figure; +hold on; +pspectrum(fjuh_e, 1e4, 'spectrogram', ... + 'FrequencyResolution', 1e0, ... + 'OverlapPercent', 99, ... + 'FrequencyLimits', [1, 400]); +plot((1/60)*time(time > 1), -(1/(5e-6))*fjur_vel(time > 1), 'k--') +hold off; +xlim([0.03, 1.14]); ylim([1, 400]); +caxis([-160, -130]) +title(''); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/lut_step_meas_pos_error_spectrogram.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:lut_step_meas_pos_error_spectrogram +#+caption: Spectrogram of the $u_h$ errors. The black dashed line corresponds to an error with a period of $5\,\mu m$ +#+RESULTS: +[[file:figs/lut_step_meas_pos_error_spectrogram.png]] + +#+begin_important +As we would like to only measure the repeatable mechanical errors of the fast jacks and not the vibrations of natural frequencies of the system, we have to filter the data. +#+end_important + +** Filtering of Data +As seen in Figure [[fig:lut_step_meas_pos_error_spectrogram]], the errors we wish to calibrate are below 160Hz while the vibrations we wish to ignore are above 200Hz. +We have to use a low pass filter that does not affects frequencies below 160Hz while having good rejection above 200Hz. + +The filter used for current LUT is a moving average filter with a length of 100: +#+begin_src matlab +%% Moving Average Filter +B_mov_avg = 1/101*ones(101,1); % FIR Filter coeficients +#+end_src + +We may also try a second order low pass filter: +#+begin_src matlab +%% 2nd order Low Pass Filter +G_lpf = 1/(1 + 2*s/(2*pi*80) + s^2/(2*pi*80)^2); +#+end_src + +And a FIR filter with linear phase: +#+begin_src matlab +%% FIR with Linear Phase +Fs = 1e4; % Sampling Frequency [Hz] +B_fir = firls(1000, ... % Filter's order + [0 140/(Fs/2) 180/(Fs/2) 1], ... % Frequencies [Hz] + [1 1 0 0]); % Wanted Magnitudes +#+end_src + +Filters' responses are computed and compared in the Bode plot of Figure [[fig:step_lut_filters_bode_plot]]. +#+begin_src matlab +%% Computation of filters' responses +[h_mov_avg, f] = freqz(B_mov_avg, 1, 10000, Fs); +[h_fir, ~] = freqz(B_fir, 1, 10000, Fs); +h_lpf = squeeze(freqresp(G_lpf, f, 'Hz')); +#+end_src + +#+begin_src matlab :exports none +%% Bode plot of different filters that could be used +figure; +tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile([2,1]); +hold on; +plot(f, abs(h_mov_avg), 'DisplayName', 'Moving Average'); +plot(f, abs(h_fir), 'DisplayName', 'FIR'); +plot(f, abs(h_lpf), 'DisplayName', '2nd order LPF'); +hold off; +set(gca, 'YScale', 'log'); +ylabel('Amplitude'); set(gca, 'XTickLabel',[]); +ylim([2e-5, 2e0]); +legend('location', 'northeast'); + +ax2 = nexttile; +hold on; +plot(f, 180/pi*angle(h_mov_avg)); +plot(f, 180/pi*angle(h_fir)); +plot(f, 180/pi*angle(h_lpf)); +hold off; +set(gca, 'YScale', 'lin'); +xlabel('Frequency [Hz]'); ylabel('Phase [deg]'); +hold off; +yticks(-360:90:360); + +linkaxes([ax1,ax2],'x'); +set(gca, 'XScale', 'lin'); +xlim([0, 5e2]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_filters_bode_plot.pdf', 'width', 'wide', 'height', 'tall'); +#+end_src + +#+name: fig:step_lut_filters_bode_plot +#+caption: Bode plot of filters that could be used before making the LUT +#+RESULTS: +[[file:figs/step_lut_filters_bode_plot.png]] + +Clearly, the currently used moving average filter is filtering too much below 160Hz and too little above 200Hz. +The FIR filter seems more suited for this case. + +Let's now compare the filtered data. +#+begin_src matlab +fjur_e_cur = filter(B_mov_avg, 1, fjur_e); +fjur_e_fir = filter(B_fir, 1, fjur_e); +fjur_e_lpf = lsim(G_lpf, fjur_e, time); +#+end_src + +As the FIR filter introduce some delays, we can identify this relay and shift the filtered data: +#+begin_src matlab +%% Compensate the FIR delay +delay = mean(grpdelay(B_fir)); +#+end_src + +#+begin_src matlab :results value replace :exports results :tangle no +ans = delay +#+end_src + +#+RESULTS: +: 500 + +#+begin_src matlab +fjur_e_fir(1:end-delay) = fjur_e_fir(delay+1:end); +#+end_src + +The same is done for the moving average filter +#+begin_src matlab +%% Compensate the Moving average delay +delay = mean(grpdelay(B_mov_avg)); +fjur_e_cur(1:end-delay) = fjur_e_cur(delay+1:end); +#+end_src + +The raw and filtered motion errors are displayed in Figure [[fig:step_lut_filtered_errors_comp]]. + +#+begin_important +It is shown that while the moving average average filter is working relatively well for low speeds (at around 20mm) it is not for high speeds (near 15mm). +This is because the frequency of the error is above 100Hz and the moving average is flipping the sign of the filtered data. + +The IIR low pass filter has some phase issues. + +Finally the FIR filter is perfectly in phase while showing good attenuation of the disturbances. +#+end_important + +#+begin_src matlab :exports none +%% Plot of the position error of the FJ as a function of their wanted positions +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(1e3*fjur, 1e6*fjur_e, 'k-', ... + 'DisplayName', 'Raw Data'); +set(gca,'ColorOrderIndex',1) +plot(1e3*fjur, 1e6*fjur_e_cur, '-', ... + 'DisplayName', 'Mov Avg'); +plot(1e3*fjur, 1e6*fjur_e_fir, '-', ... + 'DisplayName', 'FIR'); +plot(1e3*fjur, 1e6*fjur_e_lpf, '-', ... + 'DisplayName', 'LPF'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Measured Error [$\mu$m]'); +legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 2); +axis square; +xlim([14.99, 15.01]); + +ax2 = nexttile(); +hold on; +plot(1e3*fjur, 1e6*fjur_e, 'k-', ... + 'DisplayName', 'Raw Data'); +set(gca,'ColorOrderIndex',1) +plot(1e3*fjur, 1e6*fjur_e_cur, '-', ... + 'DisplayName', 'Mov Avg'); +plot(1e3*fjur, 1e6*fjur_e_fir, '-', ... + 'DisplayName', 'FIR'); +plot(1e3*fjur, 1e6*fjur_e_lpf, '-', ... + 'DisplayName', 'LPF'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Measured Error [$\mu$m]'); +legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 2); +axis square; +xlim([19.99, 20.01]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_filtered_errors_comp.pdf', 'width', 'full', 'height', 'tall'); +#+end_src + +#+name: fig:step_lut_filtered_errors_comp +#+caption: Raw measured error and filtered data +#+RESULTS: +[[file:figs/step_lut_filtered_errors_comp.png]] + +If we now look at the measured position as a function of the IcePAP steps (Figure [[fig:step_lut_filtered_motion_comp]]), we can see that we obtain a monotonous function for the FIR filtered data which is great to make the LUT. + +#+begin_src matlab :exports none +%% Plot of the measured position of the FJ as a function of their wanted positions +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(1e3*fjur, 1e3*(fjur + fjur_e), '-', ... + 'DisplayName', 'Raw Data'); +plot(1e3*fjur, 1e3*(fjur + fjur_e_fir), '-', ... + 'DisplayName', 'FIR'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Measured Position [mm]'); +legend('location', 'southeast', 'FontSize', 8); +axis square; +xlim([14.99, 15.01]); ylim([14.99, 15.01]); +xticks([14.99 14.995 15 15.005 15.01]); +yticks([14.99 14.995 15 15.005 15.01]); +xtickangle(45); +ytickangle(90); + +ax2 = nexttile(); +hold on; +plot(1e3*fjur, 1e3*(fjur + fjur_e), '-', ... + 'DisplayName', 'Raw Data'); +plot(1e3*fjur, 1e3*(fjur + fjur_e_fir), '-', ... + 'DisplayName', 'FIR'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Measured Position [mm]'); +legend('location', 'southeast', 'FontSize', 8); +axis square; +xlim([19.99, 20.01]); ylim([19.99, 20.01]); +xticks([19.99 19.995 20 20.005 20.01]); +yticks([19.99 19.995 20 20.005 20.01]); +xtickangle(45); +ytickangle(90); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_filtered_motion_comp.pdf', 'width', 'full', 'height', 'tall'); +#+end_src + +#+name: fig:step_lut_filtered_motion_comp +#+caption: Raw measured motion and filtered motion as a function of the IcePAP Steps +#+RESULTS: +[[file:figs/step_lut_filtered_motion_comp.png]] + +If we subtract the raw data with the FIR filtered data, we obtain the remaining motion shown in Figure [[fig:step_lut_remain_motion_remove_filtered]] that only contains the high frequency motion not filtered. + +#+begin_src matlab :exports none +%% Remaining motion after removing the filtered data +figure; +hold on; +plot(1e3*fjur, 1e6*(fjur_e - fjur_e_fir), 'k-'); +hold off; +xlabel('IcePAP Steps [mm]'); ylabel('Measured Error [$\mu$m]'); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_remain_motion_remove_filtered.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:step_lut_remain_motion_remove_filtered +#+caption: Remaining motion error after removing the filtered part +#+RESULTS: +[[file:figs/step_lut_remain_motion_remove_filtered.png]] + +** LUT creation +The procedure used to make the Lookup Table is schematically represented in Figure [[fig:step_lut_schematic_principle]]. + +For each IcePAP step separated by a constant value (typically $1\,\mu m$) a point of the LUT is computed: +- Points where the measured position is close to the wanted ideal position (i.e. the current IcePAP step) are found +- The corresponding IcePAP step at which the Fast Jack is at the wanted position is stored in the LUT + +Therefore the LUT gives the IcePAP step for which the fast jack is at the wanted position as measured by the metrology, which is what we want. + +#+begin_src matlab :exports none +%% Schematic of the LUT creation principle +figure; +hold on; +plot(1e3*fjur, 1e3*(fjur + fjur_e_fir), '-'); +plot(1e3*fjur, 1e3*fjur, 'k--'); +plot(20, 20, 'ko') +xline(20,'-',{'LUT Indice'}); +yline(20,'-',{'Measured Position'}); +[~, i] = min(abs(1e3*(fjur + fjur_e_fir) - 20)); +plot(1e3*(fjur(i)), 20, 'ko') +xline(1e3*(fjur(i)),'-',{'Step stored in the LUT'}); +q = quiver([20, 20],[19.992, 19.992],[-0.002, 0.002],[0,0], 'k-', 'LineWidth', 1); +q.MaxHeadSize = 0.5; +q.Marker = 'x'; +hold off; +xlabel('IcePAP Steps'); ylabel('Measured Position'); +set(gca,'Xticklabel',[]); set(gca,'Yticklabel',[]); +axis square; +xlim([19.99, 20.01]); ylim([19.99, 20.01]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_schematic_principle.pdf', 'width', 'wide', 'height', 'tall'); +#+end_src + +#+name: fig:step_lut_schematic_principle +#+caption: Schematic of the principle used to make the Lookup Table +#+RESULTS: +[[file:figs/step_lut_schematic_principle.png]] + +Let's first initialize the LUT which is table with 4 columns and 26001 rows. +The columns are: +1. IcePAP Step indices from 0 to 26mm with a step of $1\,\mu m$ (thus the 26001 rows) +2. IcePAP step for =fjur= at which point the fast jack is at the wanted position +3. Same for =fjuh= +4. Same for =fjd= + +All the units of the LUT are in mm. +We will work in meters and convert to mm at the end. + +Let's initialize the Lookup table: +#+begin_src matlab +%% Initialization of the LUT +lut = [0:1e-6:26e-3]'*ones(1,4); +#+end_src + +And verify that it has the wanted size: +#+begin_src matlab :results output replace :exports results :tangle no +size(lut) +#+end_src + +#+RESULTS: +: size(lut) +: ans = +: 26001 4 + +The measured Fast Jack position are filtered using the FIR filter: +#+begin_src matlab +%% FIR Filter +Fs = 1e4; % Sampling Frequency [Hz] +fir_order = 1000; % Filter's order +delay = fir_order/2; % Delay induced by the filter +B_fir = firls(fir_order, ... % Filter's order + [0 140/(Fs/2) 180/(Fs/2) 1], ... % Frequencies [Hz] + [1 1 0 0]); % Wanted Magnitudes + +%% Filtering all measured Fast Jack Position using the FIR filter +fjur_e_filt = filter(B_fir, 1, fjur_e); +fjuh_e_filt = filter(B_fir, 1, fjuh_e); +fjd_e_filt = filter(B_fir, 1, fjd_e); + +%% Compensation of the delay introduced by the FIR filter +fjur_e_filt(1:end-delay) = fjur_e_filt(delay+1:end); +fjuh_e_filt(1:end-delay) = fjuh_e_filt(delay+1:end); +fjd_e_filt( 1:end-delay) = fjd_e_filt( delay+1:end); +#+end_src + +The indices where the LUT will be populated are initialized. +#+begin_src matlab +%% Vector of Fast Jack positions [unit of lut_inc] +fjur_pos = floor(min(1e6*fjur)):floor(max(1e6*fjur)); +fjuh_pos = floor(min(1e6*fjuh)):floor(max(1e6*fjuh)); +fjd_pos = floor(min(1e6*fjd )):floor(max(1e6*fjd )); +#+end_src + +And the LUT is computed and shown in Figure [[fig:step_lut_obtained_lut]]. +#+begin_src matlab +%% Build the LUT +for i = fjur_pos + % Find indices where measured motion is close to the wanted one + indices = fjur + fjur_e_filt > lut(i,1) - 500e-9 & ... + fjur + fjur_e_filt < lut(i,1) + 500e-9; + % Poputate the LUT with the mean of the IcePAP steps + lut(i,2) = mean(fjur(indices)); +end + +for i = fjuh_pos + % Find indices where measuhed motion is close to the wanted one + indices = fjuh + fjuh_e_filt > lut(i,1) - 500e-9 & ... + fjuh + fjuh_e_filt < lut(i,1) + 500e-9; + % Poputate the LUT with the mean of the IcePAP steps + lut(i,3) = mean(fjuh(indices)); +end + +for i = fjd_pos + % Poputate the LUT with the mean of the IcePAP steps + indices = fjd + fjd_e_filt > lut(i,1) - 500e-9 & ... + fjd + fjd_e_filt < lut(i,1) + 500e-9; + % Poputate the LUT + lut(i,4) = mean(fjd(indices)); +end +#+end_src + +#+begin_src matlab :exports none +%% Plot the LUT +figure; +hold on; +plot(1e3*lut(:,1), 1e3*lut(:,2), '-o', ... + 'DisplayName', '$u_r$'); +plot(1e3*lut(:,1), 1e3*lut(:,3), '-o', ... + 'DisplayName', '$u_h$'); +plot(1e3*lut(:,1), 1e3*lut(:,4), '-o', ... + 'DisplayName', '$d$'); +plot(1e3*lut(:,1), 1e3*lut(:,1), 'k--', ... + 'HandleVisibility', 'off'); +hold off; +xlabel('Input IcePAP Step'); ylabel('Output IcePAP Step'); +axis square; +legend('location', 'northwest'); +set(gca,'Xticklabel',[]); set(gca,'Yticklabel',[]); +xlim([19.99, 20.01]); ylim([19.99, 20.01]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_obtained_lut.pdf', 'width', 'wide', 'height', 'tall'); +#+end_src + +#+name: fig:step_lut_obtained_lut +#+caption: Lookup Table correction +#+RESULTS: +[[file:figs/step_lut_obtained_lut.png]] + +** Cubic Interpolation of the LUT +Once the LUT is built and loaded to the IcePAP, generated steps are taking the step values in the LUT and cubic spline interpolation is performed. + +#+begin_src matlab +%% Estimation of the IcePAP output steps after interpolation +fjur_out_steps = spline(lut(:,1), lut(:,2), fjur); +#+end_src + +The LUT data points as well as the spline interpolation values and the ideal values are compared in Figure [[fig:step_lut_spline_interpolation_lut]]. +It is shown that the spline interpolation seems to be quite accurate. + +#+begin_src matlab :exports none +%% Plot the LUT +figure; +hold on; +plot(1e3*lut(:,1), 1e3*lut(:,2), 'o', ... + 'DisplayName', 'LUT Data Points'); +plot(1e3*fjur, 1e3*fjur_out_steps, '-', ... + 'DisplayName', 'Spline Interpolation'); +plot(1e3*(fjur + fjur_e_fir), 1e3*fjur, '-', ... + 'DisplayName', 'Ideal Value'); +plot(1e3*lut(:,1), 1e3*lut(:,1), 'k--', ... + 'HandleVisibility', 'off'); +hold off; +xlabel('Input IcePAP Step'); ylabel('Output IcePAP Step'); +axis square; +legend('location', 'northwest'); +xlim([14.99, 15.01]); ylim([14.99, 15.01]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_spline_interpolation_lut.pdf', 'width', 'wide', 'height', 'tall'); +#+end_src + +#+name: fig:step_lut_spline_interpolation_lut +#+caption: Output IcePAP Steps avec spline interpolation compared with the ideal steps +#+RESULTS: +[[file:figs/step_lut_spline_interpolation_lut.png]] + +The difference between the perfect step generation and the step generated after spline interpolation is shown in Figure [[fig:step_lut_error_after_interpolation]]. +The remaining position error is in the order of 100nm peak to peak which is acceptable here. + +#+begin_src matlab :exports none +%% Estimation of the Error due to limited number of points / interpolation +figure; +hold on; +plot(1e3*(fjur + fjur_e_fir), 1e9*(fjur - spline(lut(:,1), lut(:,2), fjur + fjur_e_fir)), 'k-'); +hold off; +xlabel('Input IcePAP Step [mm]'); ylabel('Output Step Error [nm]'); +xlim([14.99, 15.01]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/step_lut_error_after_interpolation.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:step_lut_error_after_interpolation +#+caption: Errors on the computed IcePAP output steps after LUT generation and spline interpolation +#+RESULTS: +[[file:figs/step_lut_error_after_interpolation.png]] + + +* Test Matlab LUT +** LUT Creation +A =thtraj= scan from 10 to 70 deg is performed. + +#+begin_src matlab +%% Extract measurement Data make from BLISS +data_ol = extractDatData("/home/thomas/mnt/data_id21/21Nov/blc13420/id21/LUT_Matlab/lut_matlab_22122021_1610.dat", ... + {"bragg", "dz", "dry", "drx", "fjur", "fjuh", "fjd"}, ... + ones(7,1)); +data_ol.time = 1e-4*[1:1:length(data_ol.bragg)]; +save("/tmp/data_lut.mat", "-struct", "data_ol"); +#+end_src + +A LUT is generated from this Data. +#+begin_src matlab +%% Generate LUT +createLUT("/tmp/data_lut.mat", "lut_matlab_22122021_1610_10_70_table.dat"); +#+end_src + +#+begin_src matlab +%% Load the generated LUT +data_lut = importdata("lut_matlab_22122021_1610_10_70_table.dat"); +#+end_src + +The generated LUT is shown in Figure [[fig:generated_matlab_lut_10_70]]. + +#+begin_src matlab :exports none +%% Plot LUT Data +figure; +hold on; +plot(data_lut(:,1), 1e3*(data_lut(:,1)-data_lut(:,2)), ... + 'DisplayName', '$u_r$'); +plot(data_lut(:,1), 1e3*(data_lut(:,1)-data_lut(:,3)), ... + 'DisplayName', '$u_h$'); +plot(data_lut(:,1), 1e3*(data_lut(:,1)-data_lut(:,4)), ... + 'DisplayName', '$d$'); +hold off; +xlabel('IcePAP Step [mm]'); ylabel('Step Offset [$\mu$m]') +xlim([15, 25]); +legend('location', 'northeast'); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/generated_matlab_lut_10_70.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:generated_matlab_lut_10_70 +#+caption: Generated LUT +#+RESULTS: +[[file:figs/generated_matlab_lut_10_70.png]] + +** Compare Mode A and Mode B +The LUT is loaded into BLISS and a new scan in mode B is performed. +#+begin_src matlab +%% Load mode B scan data +data_B = extractDatData("/home/thomas/mnt/data_id21/21Nov/blc13420/id21/LUT_Matlab/lut_matlab_result_22122021_1616.dat", ... + {"bragg", "dz", "dry", "drx", "fjur", "fjuh", "fjd"}, ... + ones(7,1)); +data_B.time = 1e-4*[1:1:length(data_B.bragg)]; +save("/tmp/data_lut.mat", "-struct", "data_ol"); +#+end_src + +#+begin_src matlab :exports none +%% Take only data during scan +data_ol_filt = data_ol.bragg > 11 & data_ol.bragg < 69; +data_B_filt = data_B.bragg > 11 & data_B.bragg < 69; +#+end_src + +#+begin_src matlab :exports none +%% Actuator Jacobian +J_a_111 = [1, 0.14, -0.0675 + 1, 0.14, 0.1525 + 1, -0.14, 0.0425]; + +%% Convert data in frame of the fast jacks +data_ol_ddz = 10.5e-3./(2*cos(pi/180*data_ol.bragg)) - 1e-9*data_ol.dz; +error = J_a_111 * [data_ol_ddz, 1e-9*data_ol.dry, 1e-9*data_ol.drx]'; + +data_ol_fjur_e = error(1,:)'; % [m] +data_ol_fjuh_e = error(2,:)'; % [m] +data_ol_fjd_e = error(3,:)'; % [m] + +data_B_ddz = 10.5e-3./(2*cos(pi/180*data_B.bragg)) - 1e-9*data_B.dz; +error = J_a_111 * [data_B_ddz, 1e-9*data_B.dry, 1e-9*data_B.drx]'; + +data_B_fjur_e = error(1,:)'; % [m] +data_B_fjuh_e = error(2,:)'; % [m] +data_B_fjd_e = error(3,:)'; % [m] +#+end_src + +#+begin_src matlab :exports none +%% Compare RAW data - Mode A and Mode B +figure; +tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(data_ol.bragg(data_ol_filt), 1e6*data_ol_fjur_e(data_ol_filt), ... + 'DisplayName', 'Mode A - $u_r$') +plot(data_B.bragg(data_B_filt), 1e6*data_B_fjur_e( data_B_filt), ... + 'DisplayName', 'Mode B - $u_r$') +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Fast Jack Error [um]') +legend('location', 'northwest') + +ax2 = nexttile(); +hold on; +plot(data_ol.bragg(data_ol_filt), 1e6*data_ol_fjuh_e(data_ol_filt), ... + 'DisplayName', 'Mode A - $u_h$') +plot(data_B.bragg(data_B_filt), 1e6*data_B_fjuh_e( data_B_filt), ... + 'DisplayName', 'Mode B - $u_h$') +hold off; +xlabel('Bragg Angle [deg]'); set(gca, 'YTickLabel',[]); +legend('location', 'northwest') + +ax3 = nexttile(); +hold on; +plot(data_ol.bragg(data_ol_filt), 1e6*data_ol_fjd_e(data_ol_filt), ... + 'DisplayName', 'Mode A - $d$') +plot(data_B.bragg(data_B_filt), 1e6*data_B_fjd_e( data_B_filt), ... + 'DisplayName', 'Mode B - $d$') +hold off; +xlabel('Bragg Angle [deg]'); set(gca, 'YTickLabel',[]); +legend('location', 'northwest') + +linkaxes([ax1,ax2,ax3],'xy'); +xlim([11, 69]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/matlab_lut_comp_fj_raw.pdf', 'width', 'full', 'height', 'tall'); +#+end_src + +#+name: fig:matlab_lut_comp_fj_raw +#+caption: Comparison of the Raw measurement of fast jack motion errors for mode A and mode B +#+RESULTS: +[[file:figs/matlab_lut_comp_fj_raw.png]] + +Now look at the low frequency motion by using a low pass filter +#+begin_src matlab +%% FIR Filter +Fs = 1e4; % Sampling Frequency [Hz] +fir_order = 1000; % Filter's order +delay = fir_order/2; % Delay induced by the filter +B_fir = firls(fir_order, ... % Filter's order + [0 5/(Fs/2) 10/(Fs/2) 1], ... % Frequencies [Hz] + [1 1 0 0]); % Wanted Magnitudes + +%% Filtering all measured Fast Jack Position using the FIR filter +data_B_fjur_f = filter(B_fir, 1, data_B_fjur_e); +data_B_fjuh_f = filter(B_fir, 1, data_B_fjuh_e); +data_B_fjd_f = filter(B_fir, 1, data_B_fjd_e); + +data_ol_fjur_f = filter(B_fir, 1, data_ol_fjur_e); +data_ol_fjuh_f = filter(B_fir, 1, data_ol_fjuh_e); +data_ol_fjd_f = filter(B_fir, 1, data_ol_fjd_e); + +%% Compensation of the delay introduced by the FIR filter +data_B_fjur_f(1:end-delay) = data_B_fjur_f(delay+1:end); +data_B_fjuh_f(1:end-delay) = data_B_fjuh_f(delay+1:end); +data_B_fjd_f( 1:end-delay) = data_B_fjd_f( delay+1:end); + +data_ol_fjur_f(1:end-delay) = data_ol_fjur_f(delay+1:end); +data_ol_fjuh_f(1:end-delay) = data_ol_fjuh_f(delay+1:end); +data_ol_fjd_f( 1:end-delay) = data_ol_fjd_f( delay+1:end); +#+end_src + +#+begin_src matlab :exports none +%% Compare RAW data - Mode A and Mode B +figure; +tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(data_ol.bragg(data_ol_filt), 1e6*data_ol_fjur_f(data_ol_filt), ... + 'DisplayName', 'Mode A - $u_r$') +plot(data_B.bragg(data_B_filt), 1e6*data_B_fjur_f( data_B_filt), ... + 'DisplayName', 'Mode B - $u_r$') +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Error for fjur [um]') +legend('location', 'northwest') + +ax2 = nexttile(); +hold on; +plot(data_ol.bragg(data_ol_filt), 1e6*data_ol_fjuh_f(data_ol_filt), ... + 'DisplayName', 'Mode A - $u_h$') +plot(data_B.bragg(data_B_filt), 1e6*data_B_fjuh_f( data_B_filt), ... + 'DisplayName', 'Mode B - $u_h$') +hold off; +xlabel('Bragg Angle [deg]'); set(gca, 'YTickLabel',[]); +legend('location', 'northwest') + +ax3 = nexttile(); +hold on; +plot(data_ol.bragg(data_ol_filt), 1e6*data_ol_fjd_f(data_ol_filt), ... + 'DisplayName', 'Mode A - $d$') +plot(data_B.bragg(data_B_filt), 1e6*data_B_fjd_f( data_B_filt), ... + 'DisplayName', 'Mode B - $d$') +hold off; +xlabel('Bragg Angle [deg]'); set(gca, 'YTickLabel',[]); +legend('location', 'northwest') + +linkaxes([ax1,ax2,ax3],'xy'); +xlim([11, 69]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/matlab_lut_comp_fj_filt.pdf', 'width', 'full', 'height', 'tall'); +#+end_src + +#+name: fig:matlab_lut_comp_fj_filt +#+caption: Comparison of the Raw measurement of fast jack motion errors for mode A and mode B +#+RESULTS: +[[file:figs/matlab_lut_comp_fj_filt.png]] + +** Check IcePAP Steps with LUT +Compare the theoretical steps and the measured steps when the LUT is on. + +Estimate wanted =fjur= steps. +#+begin_src matlab +FJ0 = 0.030427; + +fjsry = 0.53171e-3; % [rad] +fjsrx = 0.144e-3; % [rad] + +J_a_111 = [1, 0.14, -0.0675 + 1, 0.14, 0.1525 + 1, -0.14, 0.0425]; + +fjs_offset = J_a_111*[0; fjsry; fjsrx]; % ur,uh,d offsets [m] + +fjur_th = 1e3*(FJ0 + fjs_offset(1) - 10.5e-3./(2*cos(pi/180*data_B.bragg))); +#+end_src + +#+begin_src matlab +%% Estimation of the IcePAP output steps after interpolation +fjur_out_steps = spline(data_lut(:,1), data_lut(:,2), fjur_th); +#+end_src + +Difference between theoretical step using LUT and sent step using IcePAP +#+begin_src matlab +figure; +plot(data_B.bragg, 1e-2*data_B.fjur - 1e3*fjur_out_steps) +xlabel('Bragg [deg]'); ylabel('Difference on fjpur [$\mu$m]'); +xlim([10, 70]); +#+end_src + +This difference can be explained by the fact that we are basing the theoretical step after LUT on the measured Bragg angle and not on the requested one (there is a delay). + +* LUT Without =mcoil= +** Matlab Init :noexport:ignore: +#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) +<> +#+end_src + +#+begin_src matlab :exports none :results silent :noweb yes +<> +#+end_src + +#+begin_src matlab :tangle no :noweb yes +<> +#+end_src + +#+begin_src matlab :eval no :noweb yes +<> +#+end_src + +#+begin_src matlab :noweb yes +<> +#+end_src + +** Load +#+begin_src matlab +%% Extract measurement Data make from BLISS +data_ol = extractDatData("/home/thomas/mnt/data_id21/21Nov/blc13420/id21/LUT_without_mcoil/lut_without_mcoil_06012022_1644.dat", ... + {"bragg", "dz", "dry", "drx", "fjur", "fjuh", "fjd"}, ... + ones(7,1)); +data_ol.time = 1e-4*[1:1:length(data_ol.bragg)]; +% save("/tmp/data_lut.mat", "-struct", "data_ol"); +#+end_src + +#+begin_src matlab +%% Extract measurement Data make from BLISS +data_bis = extractDatData("/home/thomas/mnt/data_id21/21Nov/blc13420/id21/LUT_Matlab/lut_matlab_06012022_1651.dat", ... + {"bragg", "dz", "dry", "drx", "fjur", "fjuh", "fjd"}, ... + ones(7,1)); +data_bis.time = 1e-4*[1:1:length(data_bis.bragg)]; +% save("/tmp/data_lut.mat", "-struct", "data_ol"); +#+end_src + +#+begin_src matlab :exports none +%% Spectrogram +figure; +hold on; +pspectrum(data_ol.drx, 1e4, 'spectrogram', ... + 'FrequencyResolution', 1e0, ... + 'OverlapPercent', 99, ... + 'FrequencyLimits', [1, 400]); +% plot((1/60)*time(time > 1), -(1/(5e-6))*fjur_vel(time > 1), 'k--') +hold off; +% xlim([0.03, 1.14]); ylim([1, 400]); +% caxis([-160, -130]) +title(''); +#+end_src + +#+begin_src matlab :exports none +%% Spectrogram +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +pspectrum(data_bis.drx, 1e4, 'spectrogram', ... + 'FrequencyResolution', 1e0, ... + 'OverlapPercent', 99, ... + 'FrequencyLimits', [1, 400]); +xlim([0,10]) +caxis([-70, 70]) +title('With Mcoil'); + +ax2 = nexttile(); +pspectrum(data_ol.drx, 1e4, 'spectrogram', ... + 'FrequencyResolution', 1e0, ... + 'OverlapPercent', 99, ... + 'FrequencyLimits', [1, 400]); +xlim([0,10]) +caxis([-70, 70]) +title('Without Mcoil'); +#+end_src + +#+begin_src matlab :exports none +figure; +hold on; +plot(data_bis.time, 1e-3*data_bis.bragg) +plot(data_ol.time, 1e-3*data_ol.bragg) +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Drx [$\mu$rad]'); +#+end_src + +#+begin_src matlab :exports none +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(data_bis.bragg, 1e-3*data_bis.drx) +plot(data_ol.bragg, 1e-3*data_ol.drx) +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Drx [$\mu$rad]'); + +ax2 = nexttile(); +hold on; +plot(data_bis.bragg, 1e-3*data_bis.dry) +plot(data_ol.bragg, 1e-3*data_ol.dry) +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Dry [$\mu$rad]'); +#+end_src + +#+begin_src matlab :exports none +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(data_bis.dz, 1e-3*data_bis.drx) +plot(data_ol.dz, 1e-3*data_ol.drx) +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Drx [$\mu$rad]'); + +ax2 = nexttile(); +hold on; +plot(data_bis.dz, 1e-3*data_bis.dry) +plot(data_ol.dz, 1e-3*data_ol.dry) +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Dry [$\mu$rad]'); +#+end_src + +#+begin_src matlab +%% FIR Filter +Fs = 1e4; % Sampling Frequency [Hz] +fir_order = 1000; % Filter's order +delay = fir_order/2; % Delay induced by the filter +B_fir = firls(fir_order, ... % Filter's order + [0 5/(Fs/2) 10/(Fs/2) 1], ... % Frequencies [Hz] + [1 1 0 0]); % Wanted Magnitudes +#+end_src + +#+begin_src matlab :exports none +figure; +hold on; +plot(data_bis.bragg, 1e-3*filter(B_fir, 1, data_bis.drx)) +plot(data_ol.bragg, 1e-3*filter(B_fir, 1, data_ol.drx)) +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Dry [$\mu$rad]'); +#+end_src + +* Optimal Trajectory to make the LUT +<> +** Introduction :ignore: + +In this section, the problem of generating an adequate trajectory to make the LUT is studied. + +The problematic is the following: +1. the positioning errors of the fast jack should be measured +2. all external disturbances and measurement noise should be filtered out. + +The main difficulty is that the frequency of both the positioning errors errors and the disturbances are a function of the scanning velocity. + +First, the frequency of the disturbances as well as the errors to be measured are described and a filter is designed to optimally separate disturbances from positioning errors (Section [[sec:optimal_traj_dist]]). +The relation between the Bragg angular velocity and fast jack velocity is studied in Section [[sec:bragg_and_fj_velocities]]. +Next, a trajectory with constant fast jack velocity (Section [[sec:optimal_traj_const_fj_velocity]]) and with constant Bragg angular velocity (Section [[sec:optimal_traj_const_bragg_velocity]]) are simulated to understand their limitations. +Finally, it is proposed to perform a scan in two parts (one part with constant fast jack velocity and the other part with constant bragg angle velocity) in Section [[sec:optimal_traj_const_bragg_velocity]]. + +** Matlab Init :noexport:ignore: +#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name) +<> +#+end_src + +#+begin_src matlab :exports none :results silent :noweb yes +<> +#+end_src + +#+begin_src matlab :tangle no :noweb yes +<> +#+end_src + +#+begin_src matlab :eval no :noweb yes +<> +#+end_src + +#+begin_src matlab :noweb yes +<> +#+end_src + +** Filtering Disturbances and Noise +<> +**** Introduction :ignore: +Based on measurements made in mode A (without LUT or feedback control), several disturbances could be identified: +- vibrations coming from from the =mcoil= motor +- vibrations with constant frequencies at 29Hz (pump), 34Hz (air conditioning) and 45Hz (un-identified) + +These disturbances as well as the noise of the interferometers should be filtered out, and only the fast jack motion errors should be left untouched. + +Therefore, the goal is to make a scan such that during all the scan, the frequencies of the errors induced by the fast jack have are smaller than the frequencies of all other disturbances. +Then, it is easy to use a filter to separate the disturbances and noise from the positioning errors of the fast jack. + +**** Errors induced by the Fast Jack +The Fast Jack is composed of one stepper motor, and a planetary roller screw with a pitch of 1mm/turn. +The stepper motor as 50 pairs of magnetic poles, and therefore positioning errors are to be expected every 1/50th of turn (and its harmonics: 1/100th of turn, 1/200th of turn, etc.). + +One pair of magnetic pole corresponds to an axial motion of $20\,\mu m$. +Therefore, errors are to be expected with a period of $20\,\mu m$ and harmonics at $10\,\mu m$, $5\,\mu m$, $2.5\,\mu m$, etc. + +As the LUT has one point every $1\,\mu m$, we wish to only measure errors with a period of $20\,\mu m$, $10\,\mu m$ and $5\,\mu m$. +Indeed, errors with smaller periods are small in amplitude (i.e. not worth to compensate) and are difficult to model with the limited number of points in the LUT. + +The frequency corresponding to errors with a period of $5\,\mu m$ at 1mm/s is: +#+begin_src matlab :results value replace :exports results :tangle no +sprintf('Frequency or errors with period of 5um/s at 1mm/s is: %.1f [Hz]', 1e-3/5e-6); +#+end_src + +#+RESULTS: +: Frequency or errors with period of 5um/s at 1mm/s is: 200.0 [Hz] + +We wish that the frequency of the error corresponding to a period of $5\,\mu m$ to be smaller than the smallest disturbance to be filtered. + +As the main disturbances are at 34Hz and 45Hz, we constrain the the maximum axial velocity of the Fast Jack such that the positioning error has a frequency bellow 25Hz: +#+begin_src matlab +max_fj_vel = 25*1e-3/(1e-3/5e-6); % [m/s] +#+end_src + +#+begin_src matlab :results value replace :exports results :tangle no +sprintf('Maximum Fast Jack velocity: %.3f [mm/s]', 1e3*max_fj_vel); +#+end_src + +#+RESULTS: +: Maximum Fast Jack velocity: 0.125 [mm/s] + +#+begin_important +Therefore, the Fast Jack scans should be scanned at rather low velocity for the positioning errors to be at sufficiently low frequency. +#+end_important + +**** Vibrations induced by =mcoil= +The =mcoil= system is composed of one stepper motor and a reducer such that one stepper motor turns makes the =mcoil= axis to rotate 0.2768 degrees. +When scanning the =mcoil= motor, periodic vibrations can be measured by the interferometers. + +It has been identified that the period of these vibrations are corresponding to the period of the magnetic poles (50 per turn as for the Fast Jack stepper motors). + +Therefore, the frequency of these periodic errors are a function of the angular velocity. +With an angular velocity of 1deg/s, the frequency of the vibrations are expected to be at: +#+begin_src matlab :results value replace :exports results :tangle no +sprintf('Fundamental frequency at 1deg/s: %.1f [Hz]', 50/0.2768); +#+end_src + +#+RESULTS: +: Fundamental frequency at 1deg/s: 180.6 [Hz] + +We wish the frequency of these errors to be at minimum 34Hz (smallest frequency of other disturbances). +The corresponding minimum =mcoil= velocity is: +#+begin_src matlab +min_bragg_vel = 34/(50/0.2768); % [deg/s] +#+end_src + +#+begin_src matlab :results value replace :exports results :tangle no +sprintf('Min mcoil velocity is %.2f [deg/s]', min_bragg_vel); +#+end_src + +#+RESULTS: +: Min mcoil velocity is 0.19 [deg/s] + +#+begin_important +Regarding the =mcoil= motor, the problematic is to not scan too slowly. +It should however be checked whether the amplitude of the induced vibrations is significant of not. +#+end_important + +Note that the maximum bragg angular velocity is: +#+begin_src matlab +max_bragg_vel = 1; % [deg/s] +#+end_src + +**** Measurement noise of the interferometers + +The motion of the fast jacks are measured by interferometers which have some measurement noise. +It is wanted to filter this noise to acceptable values to have a clean measured position. + +As the interferometer noise has a rather flat spectral density, it is easy to estimate its RMS value as a function of the cut-off frequency of the filter. + +#+begin_src matlab :exports none +%% Interferometer ASD +freqs = logspace(0,3,1000); % [Hz] +asd_int = 2e-11*ones(size(freqs)); % Estimation of Interferometer ASD [m/sqrt(Hz)] +#+end_src + +The RMS value of the filtered interferometer signal as a function of the cutoff frequency of the low pass filter is computed and shown in Figure [[fig:interferometer_noise_cutoff_freq]]. +#+begin_src matlab :exports none +%% Interferometer noise as a function of Filter Frequency +figure; +plot(freqs, 1e9*sqrt(cumtrapz(freqs, asd_int.^2))) +xlabel('Filter Cutoff Frequency [Hz]'); ylabel('Filtered Noise [nm, RMS]'); +set(gca, 'XScale', 'log'); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/interferometer_noise_cutoff_freq.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:interferometer_noise_cutoff_freq +#+caption: Filtered noise RMS value as a function of the low pass filter cut-off frequency +#+RESULTS: +[[file:figs/interferometer_noise_cutoff_freq.png]] + +#+begin_important +As the filter will have a cut-off frequency between 25Hz (maximum frequency of the positioning errors) and 34Hz (minimum frequency of disturbances), a filtered measurement noise of 0.1nm RMS is to be expected. +#+end_important + +#+begin_note +Figure [[fig:interferometer_noise_cutoff_freq]] is a rough estimate. +Precise estimation can be done by measuring the spectral density of the interferometer noise experimentally. +#+end_note + +**** Interferometer - Periodic non-linearity +Interferometers can also show periodic non-linearity with a (fundamental) period equal to half the wavelength of its light (i.e. 765nm for Attocube) and with unacceptable amplitudes (up to tens of nanometers). + +The minimum frequency associated with these errors is therefore a function of the fast jack velocity. +With a velocity of 1mm/s, the frequency is: +#+begin_src matlab :results value replace :exports results :tangle no +sprintf('Fundamental frequency at 1mm/s: %.1f [Hz]', 1e-3/765e-9); +#+end_src + +#+RESULTS: +: Fundamental frequency at 1mm/s: 1307.2 [Hz] + +We wish these errors to be at minimum 34Hz (smallest frequency of other disturbances). +The corresponding minimum velocity of the Fast Jack is: +#+begin_src matlab +min_fj_vel = 34*1e-3/(1e-3/765e-9); % [m/s] +#+end_src + +#+begin_src matlab :results value replace :exports results :tangle no +sprintf('Minimum Fast Jack velocity is %.3f [mm/s]', 1e3*min_fj_vel); +#+end_src + +#+RESULTS: +: Minimum Fast Jack velocity is 0.026 [mm/s] + +#+begin_important +The Fast Jack Velocity should not be too low or the frequency of the periodic non-linearity of the interferometer would be too small to be filtered out (i.e. in the pass-band of the filter). +#+end_important + +**** Implemented Filter +Let's now verify that it is possible to implement a filter that keep everything untouched below 25Hz and filters everything above 34Hz. + +To do so, a FIR linear phase filter is designed: +#+begin_src matlab +%% FIR with Linear Phase +Fs = 1e4; % Sampling Frequency [Hz] +B_fir = firls(5000, ... % Filter's order + [0 25/(Fs/2) 34/(Fs/2) 1], ... % Frequencies [Hz] + [1 1 0 0]); % Wanted Magnitudes +#+end_src + +Its amplitude response is shown in Figure [[fig:fir_filter_response_freq_ranges]]. +It is confirmed that the errors to be measured (below 25Hz) are left untouched while the disturbances above 34Hz are reduced by at least a factor $10^4$. + +#+begin_src matlab :exports none +%% Computation of filters' responses +[h_fir, f] = freqz(B_fir, 1, 10000, Fs); +#+end_src + +#+begin_src matlab :exports none +%% Bode plot of FIR Filter with pass band and stop band +figure; +hold on; +plot(f, abs(h_fir)); +xline(25, 'k--', 'Max. Error', ... + 'LineWidth', 2, 'LabelVerticalAlignment', 'bottom'); +xline(34, 'k--', 'Min. Dist.', ... + 'LineWidth', 2, 'LabelVerticalAlignment', 'top'); +hold off; +xlabel('Frequency [Hz]'); ylabel('Amplitude'); +set(gca, 'XScale', 'lin'); set(gca, 'YScale', 'log'); +xlim([0, 50]); ylim([2e-5, 2e0]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/fir_filter_response_freq_ranges.pdf', 'width', 'wide', 'height', 'normal'); +#+end_src + +#+name: fig:fir_filter_response_freq_ranges +#+caption: FIR filter's response +#+RESULTS: +[[file:figs/fir_filter_response_freq_ranges.png]] + +To have such a steep change in gain, the order of the filter is rather large. +This has the negative effect of inducing large time delays: +#+begin_src matlab :results value replace :exports results :tangle no +sprintf('Induced time delay is %.2f [s]', (length(B_fir)-1)/2/Fs) +#+end_src + +#+RESULTS: +: Induced time delay is 0.25 [s] + +This time delay is only requiring us to start the acquisition 0.25 seconds before the important part of the scan is performed (i.e. the first 0.25 seconds of data cannot be filtered). + +** First Estimation of the optimal trajectory +<> +Based on previous analysis (Section [[sec:disturbances_noise_filtering]]), minimum and maximum fast jack velocities and bragg angular velocities could be determined. +These values are summarized in Table [[tab:max_min_vel]]. +Therefore, if during the scan the velocities are within the defined bounds, it will be very easy to filter the data and extract only the relevant information (positioning error of the fast jack). + +#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*) +data2orgtable([min_bragg_vel, max_bragg_vel; 1e3*min_fj_vel, 1e3*max_fj_vel], {'Bragg Angular Velocity [deg/s]', 'Fast Jack Velocity [mm/s]'}, {'Min', 'Max'}, ' %.3f '); +#+end_src + +#+name: tab:max_min_vel +#+caption: Minimum and Maximum estimated velocities +#+attr_latex: :environment tabularx :width 0.6\linewidth :align lXX +#+attr_latex: :center t :booktabs t +#+RESULTS: +| | Min | Max | +|--------------------------------+-------+-------| +| Bragg Angular Velocity [deg/s] | 0.188 | 1.0 | +| Fast Jack Velocity [mm/s] | 0.026 | 0.125 | + + +We now wish to see if it is possible to perform a scan from 5deg to 75deg of bragg angle while keeping the velocities within the bounds in Table [[tab:max_min_vel]]. + +To study that, we can compute the relation between the Bragg angular velocity and the Fast Jack velocity as a function of the Bragg angle. + +To do so, we first look at the relation between the Bragg angle $\theta_b$ and the Fast Jack position $d_{\text{FJ}}$: +\begin{equation} +d_{FJ}(t) = d_0 - \frac{10.5 \cdot 10^{-3}}{2 \cos \theta_b(t)} +\end{equation} +with $d_0 \approx 0.030427\,m$. + +Then, by taking the time derivative, we obtain the relation between the Fast Jack velocity $\dot{d}_{\text{FJ}}$ and the Bragg angular velocity $\dot{\theta}_b$ as a function of the bragg angle $\theta_b$: +\begin{equation} \label{eq:bragg_angle_formula} +\boxed{\dot{d}_{FJ}(t) = - \dot{\theta_b}(t) \cdot \frac{10.5 \cdot 10^{-3}}{2} \cdot \frac{\tan \theta_b(t)}{\cos \theta_b(t)}} +\end{equation} + +The relation between the Bragg angular velocity and the Fast Jack velocity is computed for several angles starting from 5degrees up to 75 degrees and this is shown in Figure [[fig:bragg_vel_fct_fj_vel]]. + +#+begin_src matlab :exports none +%% Compute Fast Jack velocities as a function of Bragg Angle and Bragg angular velocity +bragg_p = 5:5:75; % Bragg Angles [deg] +bragg_v = pi/180*[0:1e-3:1.5]; % Tested Bragg Angular Velocities [rad/s] + +[bragg_positions,bragg_velocities] = meshgrid(bragg_p,bragg_v); +fj_vel = -(bragg_velocities) .* (10.5e-3/2) .* tan(pi/180*bragg_positions)./cos(pi/180*bragg_positions); % FJ Velocity [m/s] +#+end_src + +#+begin_src matlab :exports none +%% Plot the Bragg angular velocity as a function of the FJ velocity +figure; +hold on; +contour(1e3*abs(fj_vel), 180/pi*bragg_velocities, bragg_positions, bragg_p, ... + 'ShowText', 'on', 'LineWidth', 2) +xline(1e3*min_fj_vel, 'k--', 'LineWidth', 2); +xline(1e3*max_fj_vel, 'k--', 'LineWidth', 2); +yline(min_bragg_vel, 'k--', 'LineWidth', 2); +yline(max_bragg_vel, 'k--', 'LineWidth', 2); +plot(1e3*[min_fj_vel, max_fj_vel, max_fj_vel], [max_bragg_vel, max_bragg_vel, min_bragg_vel], 'r-'); +text(1e3*(min_fj_vel+max_fj_vel)/2, max_bragg_vel, ... + '$\textcircled{1}$','Color','red','FontSize',14, 'Interpreter', 'latex', 'VerticalAlignment', 'bottom') +text(1e3*max_fj_vel, (max_bragg_vel+min_bragg_vel)/2, ... + '$\textcircled{2}$','Color','red','FontSize',14, 'Interpreter', 'latex', 'HorizontalAlignment', 'left') +hold off; +xlabel('Fast Jack Velocity [mm/s]'); +ylabel('Bragg Angular Velocity [deg/s]'); +xlim([0, 1.1*1e3*max_fj_vel]); +ylim([0, 1.1*max_bragg_vel]); +grid; +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/bragg_vel_fct_fj_vel.pdf', 'width', 'wide', 'height', 'tall'); +#+end_src + +#+name: fig:bragg_vel_fct_fj_vel +#+caption: Bragg angular velocity as a function of the fast jack velocity for several bragg angles (indicated by the colorful lines in degrees). Black dashed lines indicated minimum/maximum bragg angular velocities as well as minimum/maximum fast jack velocities +#+RESULTS: +[[file:figs/bragg_vel_fct_fj_vel.png]] + +#+begin_important +From Figure [[fig:bragg_vel_fct_fj_vel]], it is clear that only Bragg angles from apprimately 15 to 70 degrees can be scanned by staying in the "perfect" zone (defined by the dashed black lines). + +To scan smaller bragg angles, either the maximum bragg angular velocity should be increased or the minimum fast jack velocity decreased (accepting some periodic non-linearity to be measured). + +To scan higher bragg angle, either the maximum fast jack velocity should be increased or the minimum bragg angular velocity decreased (taking the risk to have some disturbances from the =mcoil= motion in the signal). +#+end_important + +For Bragg angles between 15 degrees and 70 degrees, several strategies can be chosen: +- Constant Fast Jack velocity (Figure [[fig:bragg_vel_fct_fj_vel_example_traj]] - Left): + 1. Go from 15 degrees to 44 degrees at minimum fast jack velocity + 2. Go from 44 degrees to 70 degrees at maximum fast jack velocity +- Constant Bragg angular velocity (Figure [[fig:bragg_vel_fct_fj_vel_example_traj]] - Right): + 1. Go from 15 degrees to 44 degrees at maximum angular velocity + 2. Go from 44 to 70 degrees at minimum angular velocity +- A mixed of constant bragg angular velocity and constant fast jack velocity (Figure [[fig:bragg_vel_fct_fj_vel]] - Red line) + 1. from 15 to 44 degrees with maximum Bragg angular velocity + 2. from 44 to 70 degrees with maximum Bragg angular velocity + +The third option is studied in Section [[sec:optimal_traj_const_bragg_velocity]] + +#+begin_src matlab :exports none +%% Plot the Bragg angular velocity as a function of the FJ velocity +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +contour(1e3*abs(fj_vel), 180/pi*bragg_velocities, bragg_positions, bragg_p, 'LineWidth', 2) +xline(1e3*min_fj_vel, 'k--', 'LineWidth', 2); +xline(1e3*max_fj_vel, 'k--', 'LineWidth', 2); +yline(min_bragg_vel, 'k--', 'LineWidth', 2); +yline(max_bragg_vel, 'k--', 'LineWidth', 2); +theta_mid = pi/180*44.32; +plot(1e3*[min_fj_vel, min_fj_vel], [max_bragg_vel, 180/pi*(min_fj_vel) ./( (10.5e-3/2) .* tan(theta_mid)./cos(theta_mid))], 'r-'); +plot(1e3*[min_fj_vel, max_fj_vel], [180/pi*(min_fj_vel) ./( (10.5e-3/2) .* tan(theta_mid)./cos(theta_mid)), 180/pi*(max_fj_vel) ./( (10.5e-3/2) .* tan(pi/180*44.32)./cos(pi/180*44.32))], 'r-.'); +plot(1e3*[max_fj_vel, max_fj_vel], [180/pi*(max_fj_vel) ./( (10.5e-3/2) .* tan(pi/180*44.32)./cos(pi/180*44.32)), min_bragg_vel], 'r-'); +text(1e3*min_fj_vel, (max_bragg_vel+min_bragg_vel)/2, ... + '$\textcircled{1}$','Color','red','FontSize',14, 'Interpreter', 'latex', 'HorizontalAlignment', 'right') +text(1e3*max_fj_vel, (max_bragg_vel+min_bragg_vel)/2, ... + '$\textcircled{2}$','Color','red','FontSize',14, 'Interpreter', 'latex', 'HorizontalAlignment', 'left') +hold off; +xlabel('Fast Jack Velocity [mm/s]'); +ylabel('Angular Velocity [deg/s]'); +xlim([0, 1.1*1e3*max_fj_vel]); +ylim([0, 1.1*max_bragg_vel]); +title('Constant Fast Jack Velocity') +grid; + +ax2 = nexttile(); +hold on; +contour(1e3*abs(fj_vel), 180/pi*bragg_velocities, bragg_positions, bragg_p, 'LineWidth', 2) +xline(1e3*min_fj_vel, 'k--', 'LineWidth', 2); +xline(1e3*max_fj_vel, 'k--', 'LineWidth', 2); +yline(min_bragg_vel, 'k--', 'LineWidth', 2); +yline(max_bragg_vel, 'k--', 'LineWidth', 2); +plot(1e3*[min_fj_vel, (max_bragg_vel*pi/180) .* (10.5e-3/2) .* tan(theta_mid)./cos(theta_mid)], [max_bragg_vel, max_bragg_vel], 'r-'); +plot(1e3*[(max_bragg_vel*pi/180) .* (10.5e-3/2) .* tan(theta_mid)./cos(theta_mid), (min_bragg_vel*pi/180) .* (10.5e-3/2) .* tan(theta_mid)./cos(theta_mid)], [max_bragg_vel, min_bragg_vel], 'r-.'); +plot(1e3*[(min_bragg_vel*pi/180) .* (10.5e-3/2) .* tan(theta_mid)./cos(theta_mid), max_fj_vel], [min_bragg_vel, min_bragg_vel], 'r-'); +text(1e3*(min_fj_vel+max_fj_vel)/2, max_bragg_vel, ... + '$\textcircled{1}$','Color','red','FontSize',14, 'Interpreter', 'latex', 'VerticalAlignment', 'top') +text(1e3*(min_fj_vel+max_fj_vel)/2, min_bragg_vel, ... + '$\textcircled{2}$','Color','red','FontSize',14, 'Interpreter', 'latex', 'VerticalAlignment', 'top') +hold off; +xlabel('Fast Jack Velocity [mm/s]'); +ylabel('Angular Velocity [deg/s]'); +xlim([0, 1.1*1e3*max_fj_vel]); +ylim([0, 1.1*max_bragg_vel]); +title('Constant Bragg Angular Velocity') +grid; +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/bragg_vel_fct_fj_vel_example_traj.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:bragg_vel_fct_fj_vel_example_traj +#+caption: Angular velocity and fast jack velocity during two scans from 5 to 75 degrees. On the left for a scan with constant fast jack velocity. On the right for a scan with constant Bragg angular velocity. +#+RESULTS: +[[file:figs/bragg_vel_fct_fj_vel_example_traj.png]] + +** Constant Fast Jack Velocity +<> + +In this section, a scan with constant fast jack velocity is studied. + +It was shown in Section [[sec:optimal_traj_dist]] that the maximum Fast Jack velocity should be 0.125mm/s in order for the frequency corresponding to the period of $5\,\mu m$ to be smaller than 25Hz. + +Let's generate a trajectory between 5deg and 75deg Bragg angle with constant Fast Jack velocity at 0.125mm/s. +#+begin_src matlab +%% Compute extreme fast jack position +fj_max = 0.030427 - 10.5e-3/(2*cos(pi/180*5)); % Smallest FJ position [m] +fj_min = 0.030427 - 10.5e-3/(2*cos(pi/180*75)); % Largest FJ position [m] + +%% Compute Fast Jack Trajectory +t = 0:0.1:(fj_max - fj_min)/max_fj_vel; % Time vector [s] +fj_pos = fj_max - t*max_fj_vel; % Fast Jack Position [m] + +%% Compute corresponding Bragg trajectory +bragg_pos = acos(10.5e-3./(2*(0.030427 - fj_pos))); % [rad] +#+end_src + +The Fast Jack position as well as the Bragg angle are shown as a function of time in Figure [[fig:trajectory_constant_fj_velocity]]. +#+begin_src matlab :exports none +%% Trajectory with constant Fast Jack Velocity +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +plot(t, 1e3*fj_pos); +xlabel('Time [s]'); +ylabel('Fast Jack Position [mm]') +xlim([t(1), t(end)]) + +ax2 = nexttile(); +plot(t, 180/pi*bragg_pos); +xlabel('Time [s]'); +ylabel('Bragg Angle [deg]'); +xlim([t(1), t(end)]) +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/trajectory_constant_fj_velocity.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:trajectory_constant_fj_velocity +#+caption: Trajectory with constant Fast Jack Velocity +#+RESULTS: +[[file:figs/trajectory_constant_fj_velocity.png]] + +Let's now compute the Bragg angular velocity for this scan (Figure [[fig:trajectory_constant_fj_velocity_bragg_velocity]]). +It is shown that for large Fast Jack positions / small bragg angles, the bragg angular velocity is too large. +#+begin_src matlab :exports none +%% Bragg Angular Velocity +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(180/pi*bragg_pos(1:end-1), 180/pi*(bragg_pos(2:end)-bragg_pos(1:end-1))/0.1); +plot(180/pi*[bragg_pos(1), bragg_pos(end)], [max_bragg_vel, max_bragg_vel], 'r--'); +plot(180/pi*[bragg_pos(1), bragg_pos(end)], [min_bragg_vel, min_bragg_vel], 'r--'); +hold off; +xlabel('Bragg Angle [deg]'); +ylabel('Bragg Angular Velocity [deg/s]'); +ylim([0, 5]); + +ax2 = nexttile(); +hold on; +plot(1e3*fj_pos(1:end-1), 180/pi*(bragg_pos(2:end)-bragg_pos(1:end-1))/0.1); +plot(1e3*[fj_pos(1), fj_pos(end)], [max_bragg_vel, max_bragg_vel], 'r--'); +plot(1e3*[fj_pos(1), fj_pos(end)], [min_bragg_vel, min_bragg_vel], 'r--'); +hold off; +xlabel('Fast Jack Position [mm]'); +ylabel('Bragg Angular Velocity [deg/s]'); +ylim([0, 5]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/trajectory_constant_fj_velocity_bragg_velocity.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:trajectory_constant_fj_velocity_bragg_velocity +#+caption: Bragg Velocity as a function of the bragg angle or fast jack position +#+RESULTS: +[[file:figs/trajectory_constant_fj_velocity_bragg_velocity.png]] + +#+begin_important +Between 45 and 70 degrees, the scan can be performed with *constant Fast Jack velocity* equal to 0.125 mm/s. +#+end_important + +** Constant Bragg Angular Velocity +<> + +Let's now study a scan with a constant Bragg angular velocity of 1deg/s. + +#+begin_src matlab +%% Time vector for the Scan with constant angular velocity +t = 0:0.1:(75 - 5)/max_bragg_vel; % Time vector [s] + +%% Bragg angle during the scan +bragg_pos = 5 + t*max_bragg_vel; % Bragg Angle [deg] + +%% Computation of the Fast Jack Position +fj_pos = 0.030427 - 10.5e-3./(2*cos(pi/180*bragg_pos)); % FJ position [m] +#+end_src + +#+begin_src matlab :exports none +%% Trajectory with constant Fast Jack Velocity +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +plot(t, 1e3*fj_pos); +xlabel('Time [s]'); +ylabel('Fast Jack Position [mm]') +xlim([t(1), t(end)]) + +ax2 = nexttile(); +plot(t, bragg_pos); +xlabel('Time [s]'); +ylabel('Bragg Angle [deg]'); +xlim([t(1), t(end)]) +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/trajectory_constant_bragg_velocity.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:trajectory_constant_bragg_velocity +#+caption: Trajectory with constant Bragg angular velocity +#+RESULTS: +[[file:figs/trajectory_constant_bragg_velocity.png]] + +#+begin_src matlab :exports none +%% Fast Jack Velocity +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(t(1:end-1), 1e3*abs(fj_pos(2:end)-fj_pos(1:end-1))/0.1); +plot([t(1), t(end)], 1e3*[max_fj_vel, max_fj_vel], 'r--'); +plot([t(1), t(end)], 1e3*[min_fj_vel, min_fj_vel], 'r--'); +hold off; +xlabel('Time [s]'); ylabel('Fast Jack Velocity [mm/s]'); +xlim([t(1), t(end)]); ylim([0, 1]); + +ax2 = nexttile(); +hold on; +plot(bragg_pos(1:end-1), 1e3*abs(fj_pos(2:end)-fj_pos(1:end-1))/0.1); +plot([bragg_pos(1), bragg_pos(end)], 1e3*[max_fj_vel, max_fj_vel], 'r--'); +plot([bragg_pos(1), bragg_pos(end)], 1e3*[min_fj_vel, min_fj_vel], 'r--'); +hold off; +xlabel('Bragg Position [deg]'); ylabel('Fast Jack Velocity [mm/s]'); +xlim([bragg_pos(1), bragg_pos(end)]); ylim([0, 1]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/trajectory_constant_bragg_velocity_fj_velocity.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:trajectory_constant_bragg_velocity_fj_velocity +#+caption: Fast Jack Velocity with a constant bragg angular velocity +#+RESULTS: +[[file:figs/trajectory_constant_bragg_velocity_fj_velocity.png]] + +#+begin_important +Between 15 and 45 degrees, the scan can be performed with a *constant Bragg angular velocity* equal to 1 deg/s. +#+end_important + +** Mixed Trajectory +<> + +Let's combine a scan with constant Bragg angular velocity for small bragg angles (< 44.3 deg) with a scan with constant Fast Jack velocity for large Bragg angle (> 44.3 deg). +The scan is performed from 5 degrees to 75 degrees. + +Parameters for the scan are defined below: +#+begin_src matlab +%% Bragg Positions +bragg_start = 5; % Start Bragg angle [deg] +bragg_mid = 44.3; % Transition between constant FJ vel and constant Bragg vel [deg] +bragg_end = 75; % End Bragg angle [deg] + +%% Fast Jack Positions +fj_start = 0.030427 - 10.5e-3/(2*cos(pi/180*bragg_start)); % Start FJ position [m] +fj_mid = 0.030427 - 10.5e-3/(2*cos(pi/180*bragg_mid)); % Mid FJ position [m] +fj_end = 0.030427 - 10.5e-3/(2*cos(pi/180*bragg_end)); % End FJ position [m] + +%% Time vectors +Ts = 0.1; % Sampling Time [s] +t_c_bragg = 0:Ts:(bragg_mid-bragg_start)/max_bragg_vel; % Time Vector for constant bragg velocity [s] +t_c_fj = Ts+[0:Ts:(fj_mid-fj_end)/max_fj_vel]; % Time Vector for constant Fast Jack velocity [s] +#+end_src + +Positions for the first part of the scan at constant Bragg angular velocity are computed: +#+begin_src matlab +%% Constant Bragg Angular Velocity +bragg_c_bragg = bragg_start + t_c_bragg*max_bragg_vel; % [deg] +fj_c_bragg = 0.030427 - 10.5e-3./(2*cos(pi/180*bragg_c_bragg)); % FJ position [m] +#+end_src + +And positions for the part of the scan with constant Fast Jack Velocity are computed: +#+begin_src matlab +%% Constant Bragg Angular Velocity +fj_c_fj = fj_mid - t_c_fj*max_fj_vel; % FJ position [m] +bragg_c_fj = 180/pi*acos(10.5e-3./(2*(0.030427 - fj_c_fj))); % [deg] +#+end_src + +#+begin_src matlab :exports none +%% Combine both segments +t = [t_c_bragg, t_c_fj+t_c_bragg(end)]; % Time [s] +bragg_pos = [bragg_c_bragg, bragg_c_fj]; % Bragg angle [deg] +fj_pos = [fj_c_bragg, fj_c_fj]; % FJ position [m] +#+end_src + +Fast Jack position as well as Bragg angle are displayed as a function of time in Figure [[fig:combined_scan_trajectories]]. + +#+begin_src matlab :exports none +%% Fasj Jack position and Bragg angle as a function of time +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(t, 1e3*fj_pos) +xline(t_c_bragg(end), '-', {'Transition'}, ... + 'LineWidth', 2, 'LabelVerticalAlignment', 'bottom'); +hold off; +xlabel('Time [s]'); ylabel('Fast Jack Position [mm]'); + +ax2 = nexttile(); +hold on; +plot(t, bragg_pos) +xline(t_c_bragg(end), '-', {'Transition'}, ... + 'LineWidth', 2, 'LabelVerticalAlignment', 'bottom'); +hold off; +xlabel('Time [s]'); ylabel('Bragg Angle [deg]'); + +linkaxes([ax1,ax2],'x'); +xlim([t(1), t(end)]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/combined_scan_trajectories.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:combined_scan_trajectories +#+caption: Fast jack trajectories and Bragg angular velocity during the scan +#+RESULTS: +[[file:figs/combined_scan_trajectories.png]] + +The Fast Jack velocity as well as the Bragg angular velocity are shown as a function of the Bragg angle in Figure [[fig:combined_scan_velocities]]. +#+begin_src matlab :exports none +%% Fasj Jack velocity and Bragg angular velocity as a function of time +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(bragg_pos(1:end-1), 1e3*abs(fj_pos(2:end)-fj_pos(1:end-1))/Ts) +plot([bragg_pos(1), bragg_pos(end)], 1e3*[max_fj_vel, max_fj_vel], 'r--'); +plot([bragg_pos(1), bragg_pos(end)], 1e3*[min_fj_vel, min_fj_vel], 'r--'); +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Fast Jack Velocity [mm/s]'); +xticks(5:5:75) + +ax2 = nexttile(); +hold on; +plot(bragg_pos(1:end-1), abs(bragg_pos(2:end)-bragg_pos(1:end-1))/Ts) +plot([bragg_pos(1), bragg_pos(end)], [max_bragg_vel, max_bragg_vel], 'r--'); +plot([bragg_pos(1), bragg_pos(end)], [min_bragg_vel, min_bragg_vel], 'r--'); +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Bragg Velocity [deg/s]'); +xticks(5:5:75) + +linkaxes([ax1,ax2],'x'); +xlim([bragg_pos(1), bragg_pos(end)]); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/combined_scan_velocities.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:combined_scan_velocities +#+caption: Fast jack velocity and Bragg angular velocity during the scan +#+RESULTS: +[[file:figs/combined_scan_velocities.png]] + +#+begin_important +From Figure [[fig:combined_scan_velocities]], it is shown that the fast jack velocity as well as the bragg angular velocity are within the bounds except: +- Below 15 degrees where the fast jack velocity is too small. + The frequency of the non-linear periodic errors of the interferometers would be at too low frequency (in the pass-band of the filter, see Figure [[fig:optimal_lut_trajectory_frequencies]]). + One easy option is to use an interferometer without periodic non-linearity. + Another option is to increase the maximum Bragg angular velocity to 3 deg/s. +- Above 70 degrees where the Bragg angular velocity is too small. + This may introduce low frequency disturbances induced by the =mcoil= motor that would be in the pass-band of the filter (see Figure [[fig:optimal_lut_trajectory_frequencies]]). + It should be verified if this is indeed problematic of not. + An other way would be to scan without the =mcoil= motor at very high bragg angle. +#+end_important + +In order to better visualize the filtering problem, the frequency of all the signals are shown as a function of the Bragg angle during the scan in Figure [[fig:optimal_lut_trajectory_frequencies]]. + +#+begin_src matlab :exports none +%% Disturbances coming from mcoil +mcoil_freq = 50/0.2768*abs(bragg_pos(2:end)-bragg_pos(1:end-1))/Ts; + +%% Errors Induced by the Fast Jack +fj_5u_freq = (abs(fj_pos(2:end)-fj_pos(1:end-1))/Ts)/5e-6; +fj_10u_freq = (abs(fj_pos(2:end)-fj_pos(1:end-1))/Ts)/10e-6; +fj_20u_freq = (abs(fj_pos(2:end)-fj_pos(1:end-1))/Ts)/20e-6; + +%% Periodic Non-Linearity of the interferometers +int_freq = (abs(fj_pos(2:end)-fj_pos(1:end-1))/Ts)/765e-9; + +%% Constant Disturbances +dist_freq = 34*ones(size(int_freq)); + +%% Filtering Frequency +filt_freq = 30*ones(size(int_freq)); +#+end_src + +#+begin_src matlab :exports none +%% Frequencies of signals during trajectory +figure; +tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None'); + +ax1 = nexttile(); +hold on; +plot(bragg_pos(1:end-1), fj_5u_freq, '-', 'color', colors(1,:), ... + 'DisplayName', 'FJ - $5\mu m$') +plot(bragg_pos(1:end-1), fj_10u_freq, '-.', 'color', colors(1,:), ... + 'DisplayName', 'FJ - $10\mu m$') +plot(bragg_pos(1:end-1), fj_20u_freq, '--', 'color', colors(1,:), ... + 'DisplayName', 'FJ - $20\mu m$') +plot(bragg_pos(1:end-1), mcoil_freq, '-', 'color', colors(2,:), ... + 'DisplayName', 'mcoil') +plot(bragg_pos(1:end-1), int_freq, '-.', 'color', colors(2,:), ... + 'DisplayName', 'Int.') +plot(bragg_pos(1:end-1), dist_freq, '--', 'color', colors(2,:), ... + 'DisplayName', 'Dist') +plot(bragg_pos(1:end-1), filt_freq, 'k-', ... + 'DisplayName', 'Filter') +hold off; +xlabel('Bragg Angle [deg]'); ylabel('Frequency [Hz]'); +xlim([bragg_pos(1), bragg_pos(end)]); + +ax2 = nexttile(); +hold on; +plot(1e3*fj_pos(1:end-1), fj_5u_freq, '-', 'color', colors(1,:), ... + 'DisplayName', 'FJ - $5\mu m$') +plot(1e3*fj_pos(1:end-1), fj_10u_freq, '-.', 'color', colors(1,:), ... + 'DisplayName', 'FJ - $10\mu m$') +plot(1e3*fj_pos(1:end-1), fj_20u_freq, '--', 'color', colors(1,:), ... + 'DisplayName', 'FJ - $20\mu m$') +plot(1e3*fj_pos(1:end-1), mcoil_freq, '-', 'color', colors(2,:), ... + 'DisplayName', 'mcoil') +plot(1e3*fj_pos(1:end-1), int_freq, '-.', 'color', colors(2,:), ... + 'DisplayName', 'Int. Non-Lin') +plot(1e3*fj_pos(1:end-1), dist_freq, '--', 'color', colors(2,:), ... + 'DisplayName', 'Ext. Dist.') +plot(1e3*fj_pos(1:end-1), filt_freq, 'k-', ... + 'DisplayName', 'Filter Cut-off') +hold off; +xlabel('Fast Jack Position [mm]'); ylabel('Frequency [Hz]'); +legend('location', 'northwest', 'FontSize', 8); +#+end_src + +#+begin_src matlab :tangle no :exports results :results file replace +exportFig('figs/optimal_lut_trajectory_frequencies.pdf', 'width', 'full', 'height', 'normal'); +#+end_src + +#+name: fig:optimal_lut_trajectory_frequencies +#+caption: Frequency of signals as a function of the Bragg angle and Fast Jack position +#+RESULTS: +[[file:figs/optimal_lut_trajectory_frequencies.png]] + +* Piezoelectric LUT +** Introduction :ignore: + +On main issue with implementing the LUT inside + +The idea is to: +- Correct the low frequency errors inside the IcePAP (1mm period motor error). +- This should reduce the errors to an acceptable range (within the piezoelectric stack stroke). +- Correct the high frequency errors (periods of $5\,\mu m$, $10\,\mu m$ and $20\,\mu m$) using the piezoelectric stack. + +* Generate =.dat= file :noexport: +#+begin_src matlab +lut = 1e-3*[0:1:26000]'*ones(1, 4); +#+end_src + +#+begin_src matlab :exports results :results value table replace :tangle no +data2orgtable(lut(1:10, :), {}, {}, ' %.1e '); +#+end_src + +#+RESULTS: +| 0.0 | 0.0 | 0.0 | 0.0 | +| 0.001 | 0.001 | 0.001 | 0.001 | +| 0.002 | 0.002 | 0.002 | 0.002 | +| 0.003 | 0.003 | 0.003 | 0.003 | +| 0.004 | 0.004 | 0.004 | 0.004 | +| 0.005 | 0.005 | 0.005 | 0.005 | +| 0.006 | 0.006 | 0.006 | 0.006 | +| 0.007 | 0.007 | 0.007 | 0.007 | +| 0.008 | 0.008 | 0.008 | 0.008 | +| 0.009 | 0.009 | 0.009 | 0.009 | + +#+begin_src matlab :results output replace +sprintf('%.18e %.18e %.18e %.18e\n', lut(1:10, :)') +#+end_src + +#+RESULTS: +#+begin_example +ans = + '0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 + 1.000000000000000021e-03 1.000000000000000021e-03 1.000000000000000021e-03 1.000000000000000021e-03 + 2.000000000000000042e-03 2.000000000000000042e-03 2.000000000000000042e-03 2.000000000000000042e-03 + 3.000000000000000062e-03 3.000000000000000062e-03 3.000000000000000062e-03 3.000000000000000062e-03 + 4.000000000000000083e-03 4.000000000000000083e-03 4.000000000000000083e-03 4.000000000000000083e-03 + 5.000000000000000104e-03 5.000000000000000104e-03 5.000000000000000104e-03 5.000000000000000104e-03 + 6.000000000000000125e-03 6.000000000000000125e-03 6.000000000000000125e-03 6.000000000000000125e-03 + 7.000000000000000146e-03 7.000000000000000146e-03 7.000000000000000146e-03 7.000000000000000146e-03 + 8.000000000000000167e-03 8.000000000000000167e-03 8.000000000000000167e-03 8.000000000000000167e-03 + 9.000000000000001055e-03 9.000000000000001055e-03 9.000000000000001055e-03 9.000000000000001055e-03 + ' +#+end_example + +#+begin_src matlab +%% Save lut as a .dat file +formatSpec = '%.18e %.18e %.18e %.18e\n'; + +fileID = fopen('test_lut.dat','w'); +fprintf(fileID, formatSpec, lut'); +fclose(fileID); +#+end_src + +* TODO Repeatability of the motion :noexport: +#+begin_src matlab +%% Load Data of the new LUT method +Ts = 0.1; + +ol_drx_1 = 1e-9*double(h5read('xanes_0004.h5','/15.1/measurement/xtal_111_drx_filter')); % Rx [rad] +ol_drx_2 = 1e-9*double(h5read('xanes_0004.h5','/16.1/measurement/xtal_111_drx_filter')); % Rx [rad] +ol_drx_3 = 1e-9*double(h5read('xanes_0004.h5','/17.1/measurement/xtal_111_drx_filter')); % Rx [rad] +ol_drx_4 = 1e-9*double(h5read('xanes_0004.h5','/18.1/measurement/xtal_111_drx_filter')); % Rx [rad] + +ol_dry_1 = 1e-9*double(h5read('xanes_0004.h5','/15.1/measurement/xtal_111_dry_filter')); % Ry [rad] +ol_dry_2 = 1e-9*double(h5read('xanes_0004.h5','/16.1/measurement/xtal_111_dry_filter')); % Ry [rad] +ol_dry_3 = 1e-9*double(h5read('xanes_0004.h5','/17.1/measurement/xtal_111_dry_filter')); % Ry [rad] +ol_dry_4 = 1e-9*double(h5read('xanes_0004.h5','/18.1/measurement/xtal_111_dry_filter')); % Ry [rad] + +t = linspace(Ts, Ts*length(ol_drx_1), length(ol_drx_1)); +#+end_src + +#+begin_src matlab +figure; +hold on; +plot(t, ol_drx_1) +plot(t, ol_drx_2) +plot(t, ol_drx_3) +#+end_src + +#+begin_src matlab +figure; +hold on; +plot(t, ol_dry_1) +plot(t, ol_dry_2) +plot(t, ol_dry_3) +#+end_src + +#+begin_src matlab +%% Repeatable motion +ol_drx_mean = mean([ol_drx_1, ol_drx_2, ol_drx_4 ol_drx_3]')'; +ol_dry_mean = mean([ol_dry_2, ol_dry_3, ol_dry_4]')'; +#+end_src + +#+begin_src matlab :results value replace +rms([ol_drx_1 - ol_drx_mean; + ol_drx_2 - ol_drx_mean; + ol_drx_3 - ol_drx_mean; + ol_drx_4 - ol_drx_mean;]) +#+end_src + +#+RESULTS: +: 1.0335e-07 + +#+begin_src matlab :results value replace +rms([ol_dry_2 - ol_dry_mean; + ol_dry_3 - ol_dry_mean; + ol_dry_4 - ol_dry_mean;]) +#+end_src + +#+RESULTS: +: 9.7691e-08 + +#+begin_src matlab +figure; +hold on; +plot(t, ol_drx_1 - ol_drx_mean) +plot(t, ol_drx_2 - ol_drx_mean) +plot(t, ol_drx_3 - ol_drx_mean) +plot(t, ol_drx_4 - ol_drx_mean) +#+end_src + +#+begin_src matlab +figure; +hold on; +plot(t, ol_dry_2 - ol_dry_mean) +plot(t, ol_dry_3 - ol_dry_mean) +plot(t, ol_dry_4 - ol_dry_mean) +#+end_src * Helping Functions :noexport: ** Initialize Path @@ -993,6 +3262,7 @@ Suppose we have the power spectral density (PSD) of both $n_a$ and $n_g$. #+BEGIN_SRC matlab %% Path for functions, data and scripts addpath('./matlab/mat/'); % Path for data +addpath('./matlab/src/'); % Path for functions addpath('./matlab/'); % Path for scripts #+END_SRC @@ -1000,6 +3270,7 @@ addpath('./matlab/'); % Path for scripts #+BEGIN_SRC matlab %% Path for functions, data and scripts addpath('./mat/'); % Path for data +addpath('./src/'); % Path for functions #+END_SRC ** Initialize Simscape Model @@ -1017,5 +3288,279 @@ colors = colororder; freqs = logspace(1, 3, 1000); #+END_SRC +** =loadRepeatabiltyData= +:PROPERTIES: +:header-args:matlab+: :tangle matlab/src/loadRepeatabiltyData.m +:header-args:matlab+: :comments none :mkdirp yes :eval no +:END: +<> + +*** Function description :ignore: + +Function description: + +#+begin_src matlab -n +function [data] = loadRepeatabiltyData(filename, path) +% loadRepeatabiltyData - +% +% Syntax: [ref] = loadRepeatabiltyData(args) +% +% Inputs: +% - args +% +% Outputs: +% - ref - Reference Signal +#+end_src + +*** Load Data :ignore: + +#+begin_src matlab +n +data = struct(); + +data.bragg = (pi/180)*1e-6*double(h5read(filename, ['/', path, '/instrument/trajmot/data'])); % Bragg angle [rad] +data.dzw = 10.5e-3./(2*cos(data.bragg)); % Wanted distance between crystals [m] + +data.dz = 1e-9*double(h5read(filename, ['/', path, '/instrument/xtal_111_dz/data' ])); % Dz distance between crystals [m] +data.dry = 1e-9*double(h5read(filename, ['/', path, '/instrument/xtal_111_dry/data'])); % Ry [rad] +data.drx = 1e-9*double(h5read(filename, ['/', path, '/instrument/xtal_111_drx/data'])); % Rx [rad] + +data.t = 1e-6*double(h5read(filename, ['/', path, '/instrument/time/data'])); % Time [s] + +data.ddz = data.dzw-data.dz; % Distance Error between crystals [m] +#+end_src + +** =computeErrorFJ= +:PROPERTIES: +:header-args:matlab+: :tangle matlab/src/computeErrorFJ.m +:header-args:matlab+: :comments none :mkdirp yes :eval no +:END: +<> + +*** Function description :ignore: + +Function description: + +#+begin_src matlab -n +function [data] = computeErrorFJ(data) +% computeErrorFJ - +% +% Syntax: [data] = computeErrorFJ(data) +% +% Inputs: +% - args +% +% Outputs: +% - ref - Reference Signal +#+end_src + +*** Load Data :ignore: + +#+begin_src matlab +n +J_a_111 = [1, 0.14, -0.0675 + 1, 0.14, 0.1525 + 1, -0.14, 0.0425]; + +error = [-data.dzm, data.rym, data.rxm] * J_a_111; + +data.fjur_e = error(:,1); % [m] +data.fjuh_e = error(:,2); % [m] +data.fjd_e = error(:,3); % [m] +#+end_src + +** =createLUT= +:PROPERTIES: +:header-args:matlab+: :tangle matlab/src/createLUT.m +:header-args:matlab+: :comments none :mkdirp yes :eval no +:END: +<> + +*** Function Description +#+begin_src matlab +function [] = createLUT(data_file, lut_file, args) +% createLUT - +% +% Syntax: createLUT(data_file, lut_file, args) +% +% Inputs: +% - data_file - Where to load the .mat file +% - lut_file - Where to save the .dat file +% - args: +% - plot - Should plot data for diagnostic (default: false) +% - update - Should update LUT file instead of creating from scratch (default: true) +#+end_src + +*** Optional Parameters +#+begin_src matlab +arguments + data_file + lut_file + args.plot (1,1) logical {mustBeNumericOrLogical} = false + args.update (1,1) logical {mustBeNumericOrLogical} = false + args.fjsry (1,1) double {mustBeNumeric} = 0.53171e-3 % [Rad] + args.fjsrx (1,1) double {mustBeNumeric} = 0.144e-3 % [Rad] + args.FJ0 (1,1) double {mustBeNumeric} = 0.0304274021077198 % [m] +end +#+end_src + +*** Load Data +#+begin_src matlab +%% Load Data +load(data_file) +#+end_src + +#+begin_src matlab +%% Convert Data to Standard Units +% Bragg Angle [rad] +bragg = pi/180*bragg; +% Rx rotation of 1st crystal w.r.t. 2nd crystal [rad] +drx = 1e-9*drx; +% Ry rotation of 1st crystal w.r.t. 2nd crystal [rad] +dry = 1e-9*dry; +% Z distance between crystals [m] +dz = 1e-9*dz; +% Z error between second crystal and first crystal [m] +ddz = 10.5e-3./(2*cos(bragg)) - dz; +% Steps for Ur motor [m] +fjur = 1e-8*fjur; +% Steps for Uh motor [m] +fjuh = 1e-8*fjuh; +% Steps for D motor [m] +fjd = 1e-8*fjd; +#+end_src + +*** Compute the Fast Jack errors +#+begin_src matlab +%% Actuator Jacobian +J_a_111 = [1, 0.14, -0.0675 + 1, 0.14, 0.1525 + 1, -0.14, 0.0425]; + +%% Computation of the position of the FJ as measured by the interferometers +error = J_a_111 * [ddz, dry, drx]'; + +fjur_e = error(1,:)'; % [m] +fjuh_e = error(2,:)'; % [m] +fjd_e = error(3,:)'; % [m] +#+end_src + +*** Filtering of Fast Jack Errors +#+begin_src matlab +%% FIR Filter +Fs = round(1/((time(end)-time(1))/(length(time) - 1))); % Sampling Frequency [Hz] +fir_order = 1000; % Filter's order +delay = fir_order/2; % Delay induced by the filter +B_fir = firls(fir_order, ... % Filter's order + [0 140/(Fs/2) 180/(Fs/2) 1], ... % Frequencies [Hz] + [1 1 0 0]); % Wanted Magnitudes + +%% Filtering all measured Fast Jack Position using the FIR filter +fjur_e_filt = filter(B_fir, 1, fjur_e); +fjuh_e_filt = filter(B_fir, 1, fjuh_e); +fjd_e_filt = filter(B_fir, 1, fjd_e); + +%% Compensation of the delay introduced by the FIR filter +fjur_e_filt(1:end-delay) = fjur_e_filt(delay+1:end); +fjuh_e_filt(1:end-delay) = fjuh_e_filt(delay+1:end); +fjd_e_filt( 1:end-delay) = fjd_e_filt( delay+1:end); +#+end_src + +*** LUT Creation +#+begin_src matlab +%% Lut Initialization +lut = [0:1e-6:26e-3]'*ones(1,4); +#+end_src + +#+begin_src matlab +%% Vector of Fast Jack positions [unit of lut_inc] +fjur_pos = floor(min(1e6*fjur)):floor(max(1e6*fjur)); +fjuh_pos = floor(min(1e6*fjuh)):floor(max(1e6*fjuh)); +fjd_pos = floor(min(1e6*fjd )):floor(max(1e6*fjd )); +#+end_src + +#+begin_src matlab +%% Build the LUT +for i = fjur_pos + % Find indices where measured motion is close to the wanted one + indices = fjur + fjur_e_filt > lut(i,1) - 500e-9 & ... + fjur + fjur_e_filt < lut(i,1) + 500e-9; + % Poputate the LUT with the mean of the IcePAP steps + if sum(indices) > 0 + lut(i,2) = mean(fjur(indices)); + end +end + +for i = fjuh_pos + % Find indices where measuhed motion is close to the wanted one + indices = fjuh + fjuh_e_filt > lut(i,1) - 500e-9 & ... + fjuh + fjuh_e_filt < lut(i,1) + 500e-9; + % Poputate the LUT with the mean of the IcePAP steps + if sum(indices) > 0 + lut(i,3) = mean(fjuh(indices)); + end +end + +for i = fjd_pos + % Poputate the LUT with the mean of the IcePAP steps + indices = fjd + fjd_e_filt > lut(i,1) - 500e-9 & ... + fjd + fjd_e_filt < lut(i,1) + 500e-9; + % Poputate the LUT + if sum(indices) > 0 + lut(i,4) = mean(fjd(indices)); + end +end +#+end_src + +#+begin_src matlab +%% Convert from [m] to [mm] +lut = 1e3*lut; +#+end_src + +*** Save the LUT +#+begin_src matlab +%% Save lut as a .dat file +formatSpec = '%.18e %.18e %.18e %.18e\n'; + +fileID = fopen(lut_file, 'w'); +fprintf(fileID, formatSpec, lut'); +fclose(fileID); +#+end_src + +** =extractDatData= +:PROPERTIES: +:header-args:matlab+: :tangle matlab/src/extractDatData.m +:header-args:matlab+: :comments none :mkdirp yes :eval no +:END: +<> + +*** Function Description +#+begin_src matlab +function [data_struct] = extractDatData(dat_file, names, scale) +% extractDatData - +% +% Syntax: extractDatData(data_file, lut_file, args) +% +% Inputs: +% - data_file - Where to load the .mat file +% - lut_file - Where to save the .dat file +#+end_src + +*** Load Data +#+begin_src matlab +%% Load Data +data_array = importdata(dat_file); +#+end_src + +#+begin_src matlab +%% Initialize Struct +data_struct = struct(); +#+end_src + +#+begin_src matlab +%% Populate Struct +for i = 1:length(names) + data_struct.(names{i}) = scale(i)*data_array(:,i); +end +#+end_src + * Bibliography :ignore: #+latex: \printbibliography diff --git a/dcm_lookup_tables.pdf b/dcm_lookup_tables.pdf index a9f7633..7d7f19e 100644 Binary files a/dcm_lookup_tables.pdf and b/dcm_lookup_tables.pdf differ diff --git a/figs/bragg_vel_fct_fj_vel.pdf b/figs/bragg_vel_fct_fj_vel.pdf new file mode 100644 index 0000000..01dd424 Binary files /dev/null and b/figs/bragg_vel_fct_fj_vel.pdf differ diff --git a/figs/bragg_vel_fct_fj_vel.png b/figs/bragg_vel_fct_fj_vel.png new file mode 100644 index 0000000..1e7610f Binary files /dev/null and b/figs/bragg_vel_fct_fj_vel.png differ diff --git a/figs/bragg_vel_fct_fj_vel_example_traj.pdf b/figs/bragg_vel_fct_fj_vel_example_traj.pdf new file mode 100644 index 0000000..4366600 Binary files /dev/null and b/figs/bragg_vel_fct_fj_vel_example_traj.pdf differ diff --git a/figs/bragg_vel_fct_fj_vel_example_traj.png b/figs/bragg_vel_fct_fj_vel_example_traj.png new file mode 100644 index 0000000..95abced Binary files /dev/null and b/figs/bragg_vel_fct_fj_vel_example_traj.png differ diff --git a/figs/combined_scan_trajectories.pdf b/figs/combined_scan_trajectories.pdf new file mode 100644 index 0000000..1a6eaa0 Binary files /dev/null and b/figs/combined_scan_trajectories.pdf differ diff --git a/figs/combined_scan_trajectories.png b/figs/combined_scan_trajectories.png new file mode 100644 index 0000000..beb92d7 Binary files /dev/null and b/figs/combined_scan_trajectories.png differ diff --git a/figs/combined_scan_velocities.pdf b/figs/combined_scan_velocities.pdf new file mode 100644 index 0000000..08a92d9 Binary files /dev/null and b/figs/combined_scan_velocities.pdf differ diff --git a/figs/combined_scan_velocities.png b/figs/combined_scan_velocities.png new file mode 100644 index 0000000..4f15c16 Binary files /dev/null and b/figs/combined_scan_velocities.png differ diff --git a/figs/fir_filter_response_freq_ranges.pdf b/figs/fir_filter_response_freq_ranges.pdf new file mode 100644 index 0000000..c1ca1d0 Binary files /dev/null and b/figs/fir_filter_response_freq_ranges.pdf differ diff --git a/figs/fir_filter_response_freq_ranges.png b/figs/fir_filter_response_freq_ranges.png new file mode 100644 index 0000000..08fda62 Binary files /dev/null and b/figs/fir_filter_response_freq_ranges.png differ diff --git a/figs/generated_matlab_lut_10_70.pdf b/figs/generated_matlab_lut_10_70.pdf new file mode 100644 index 0000000..9df5c06 Binary files /dev/null and b/figs/generated_matlab_lut_10_70.pdf differ diff --git a/figs/generated_matlab_lut_10_70.png b/figs/generated_matlab_lut_10_70.png new file mode 100644 index 0000000..9dda09e Binary files /dev/null and b/figs/generated_matlab_lut_10_70.png differ diff --git a/figs/interferometer_noise_cutoff_freq.pdf b/figs/interferometer_noise_cutoff_freq.pdf new file mode 100644 index 0000000..4f71c51 Binary files /dev/null and b/figs/interferometer_noise_cutoff_freq.pdf differ diff --git a/figs/interferometer_noise_cutoff_freq.png b/figs/interferometer_noise_cutoff_freq.png new file mode 100644 index 0000000..024d8a7 Binary files /dev/null and b/figs/interferometer_noise_cutoff_freq.png differ diff --git a/figs/lut_step_bragg_angle_error_aerotech.pdf b/figs/lut_step_bragg_angle_error_aerotech.pdf new file mode 100644 index 0000000..61325c5 Binary files /dev/null and b/figs/lut_step_bragg_angle_error_aerotech.pdf differ diff --git a/figs/lut_step_bragg_angle_error_aerotech.png b/figs/lut_step_bragg_angle_error_aerotech.png new file mode 100644 index 0000000..35d241c Binary files /dev/null and b/figs/lut_step_bragg_angle_error_aerotech.png differ diff --git a/figs/lut_step_bragg_error_fct_velocity.pdf b/figs/lut_step_bragg_error_fct_velocity.pdf new file mode 100644 index 0000000..816bfbb Binary files /dev/null and b/figs/lut_step_bragg_error_fct_velocity.pdf differ diff --git a/figs/lut_step_bragg_error_fct_velocity.png b/figs/lut_step_bragg_error_fct_velocity.png new file mode 100644 index 0000000..12c8e7d Binary files /dev/null and b/figs/lut_step_bragg_error_fct_velocity.png differ diff --git a/figs/lut_step_mean_pos_error.pdf b/figs/lut_step_mean_pos_error.pdf new file mode 100644 index 0000000..cd4181a Binary files /dev/null and b/figs/lut_step_mean_pos_error.pdf differ diff --git a/figs/lut_step_mean_pos_error.png b/figs/lut_step_mean_pos_error.png new file mode 100644 index 0000000..2878484 Binary files /dev/null and b/figs/lut_step_mean_pos_error.png differ diff --git a/figs/lut_step_meas_pos_error_spectrogram.pdf b/figs/lut_step_meas_pos_error_spectrogram.pdf new file mode 100644 index 0000000..66e6dcf Binary files /dev/null and b/figs/lut_step_meas_pos_error_spectrogram.pdf differ diff --git a/figs/lut_step_meas_pos_error_spectrogram.png b/figs/lut_step_meas_pos_error_spectrogram.png new file mode 100644 index 0000000..3ab2f24 Binary files /dev/null and b/figs/lut_step_meas_pos_error_spectrogram.png differ diff --git a/figs/lut_step_meas_pos_fct_wanted_pos.pdf b/figs/lut_step_meas_pos_fct_wanted_pos.pdf new file mode 100644 index 0000000..fd2c454 Binary files /dev/null and b/figs/lut_step_meas_pos_fct_wanted_pos.pdf differ diff --git a/figs/lut_step_meas_pos_fct_wanted_pos.png b/figs/lut_step_meas_pos_fct_wanted_pos.png new file mode 100644 index 0000000..7d29a94 Binary files /dev/null and b/figs/lut_step_meas_pos_fct_wanted_pos.png differ diff --git a/figs/lut_step_meas_pos_fct_wanted_pos_uh_repeat.pdf b/figs/lut_step_meas_pos_fct_wanted_pos_uh_repeat.pdf new file mode 100644 index 0000000..82b86ef Binary files /dev/null and b/figs/lut_step_meas_pos_fct_wanted_pos_uh_repeat.pdf differ diff --git a/figs/lut_step_meas_pos_fct_wanted_pos_uh_repeat.png b/figs/lut_step_meas_pos_fct_wanted_pos_uh_repeat.png new file mode 100644 index 0000000..b31bf46 Binary files /dev/null and b/figs/lut_step_meas_pos_fct_wanted_pos_uh_repeat.png differ diff --git a/figs/lut_step_measured_error_fj.pdf b/figs/lut_step_measured_error_fj.pdf new file mode 100644 index 0000000..dc77f20 Binary files /dev/null and b/figs/lut_step_measured_error_fj.pdf differ diff --git a/figs/lut_step_measured_error_fj.png b/figs/lut_step_measured_error_fj.png new file mode 100644 index 0000000..f975dea Binary files /dev/null and b/figs/lut_step_measured_error_fj.png differ diff --git a/figs/lut_step_measured_error_fj_zoom.pdf b/figs/lut_step_measured_error_fj_zoom.pdf new file mode 100644 index 0000000..90f7b88 Binary files /dev/null and b/figs/lut_step_measured_error_fj_zoom.pdf differ diff --git a/figs/lut_step_measured_error_fj_zoom.png b/figs/lut_step_measured_error_fj_zoom.png new file mode 100644 index 0000000..24ca82b Binary files /dev/null and b/figs/lut_step_measured_error_fj_zoom.png differ diff --git a/figs/lut_step_measured_errors.pdf b/figs/lut_step_measured_errors.pdf new file mode 100644 index 0000000..065ecb8 Binary files /dev/null and b/figs/lut_step_measured_errors.pdf differ diff --git a/figs/lut_step_measured_errors.png b/figs/lut_step_measured_errors.png new file mode 100644 index 0000000..55585ff Binary files /dev/null and b/figs/lut_step_measured_errors.png differ diff --git a/figs/matlab_lut_comp_fj_filt.pdf b/figs/matlab_lut_comp_fj_filt.pdf new file mode 100644 index 0000000..da9d822 Binary files /dev/null and b/figs/matlab_lut_comp_fj_filt.pdf differ diff --git a/figs/matlab_lut_comp_fj_filt.png b/figs/matlab_lut_comp_fj_filt.png new file mode 100644 index 0000000..4c43840 Binary files /dev/null and b/figs/matlab_lut_comp_fj_filt.png differ diff --git a/figs/matlab_lut_comp_fj_raw.pdf b/figs/matlab_lut_comp_fj_raw.pdf new file mode 100644 index 0000000..e5a9198 Binary files /dev/null and b/figs/matlab_lut_comp_fj_raw.pdf differ diff --git a/figs/matlab_lut_comp_fj_raw.png b/figs/matlab_lut_comp_fj_raw.png new file mode 100644 index 0000000..fc199c6 Binary files /dev/null and b/figs/matlab_lut_comp_fj_raw.png differ diff --git a/figs/optimal_lut_trajectory_frequencies.pdf b/figs/optimal_lut_trajectory_frequencies.pdf new file mode 100644 index 0000000..ed3df45 Binary files /dev/null and b/figs/optimal_lut_trajectory_frequencies.pdf differ diff --git a/figs/optimal_lut_trajectory_frequencies.png b/figs/optimal_lut_trajectory_frequencies.png new file mode 100644 index 0000000..0c399c6 Binary files /dev/null and b/figs/optimal_lut_trajectory_frequencies.png differ diff --git a/figs/pos_error_vs_icepap_steps.pdf b/figs/pos_error_vs_icepap_steps.pdf new file mode 100644 index 0000000..4b8a7ad Binary files /dev/null and b/figs/pos_error_vs_icepap_steps.pdf differ diff --git a/figs/pos_error_vs_icepap_steps.png b/figs/pos_error_vs_icepap_steps.png new file mode 100644 index 0000000..6c485a7 Binary files /dev/null and b/figs/pos_error_vs_icepap_steps.png differ diff --git a/figs/step_lut_bragg_vel.pdf b/figs/step_lut_bragg_vel.pdf new file mode 100644 index 0000000..9fbdcde Binary files /dev/null and b/figs/step_lut_bragg_vel.pdf differ diff --git a/figs/step_lut_bragg_vel.png b/figs/step_lut_bragg_vel.png new file mode 100644 index 0000000..134dff9 Binary files /dev/null and b/figs/step_lut_bragg_vel.png differ diff --git a/figs/step_lut_deriv_filter.pdf b/figs/step_lut_deriv_filter.pdf new file mode 100644 index 0000000..6dc7e33 Binary files /dev/null and b/figs/step_lut_deriv_filter.pdf differ diff --git a/figs/step_lut_deriv_filter.png b/figs/step_lut_deriv_filter.png new file mode 100644 index 0000000..17bfdd4 Binary files /dev/null and b/figs/step_lut_deriv_filter.png differ diff --git a/figs/step_lut_error_after_interpolation.pdf b/figs/step_lut_error_after_interpolation.pdf new file mode 100644 index 0000000..4b59e7d Binary files /dev/null and b/figs/step_lut_error_after_interpolation.pdf differ diff --git a/figs/step_lut_error_after_interpolation.png b/figs/step_lut_error_after_interpolation.png new file mode 100644 index 0000000..d4b48aa Binary files /dev/null and b/figs/step_lut_error_after_interpolation.png differ diff --git a/figs/step_lut_estimation_wanted_fj_pos.pdf b/figs/step_lut_estimation_wanted_fj_pos.pdf new file mode 100644 index 0000000..e659e08 Binary files /dev/null and b/figs/step_lut_estimation_wanted_fj_pos.pdf differ diff --git a/figs/step_lut_estimation_wanted_fj_pos.png b/figs/step_lut_estimation_wanted_fj_pos.png new file mode 100644 index 0000000..b5041e4 Binary files /dev/null and b/figs/step_lut_estimation_wanted_fj_pos.png differ diff --git a/figs/step_lut_fast_jack_vel.pdf b/figs/step_lut_fast_jack_vel.pdf new file mode 100644 index 0000000..66020ce Binary files /dev/null and b/figs/step_lut_fast_jack_vel.pdf differ diff --git a/figs/step_lut_fast_jack_vel.png b/figs/step_lut_fast_jack_vel.png new file mode 100644 index 0000000..2980d07 Binary files /dev/null and b/figs/step_lut_fast_jack_vel.png differ diff --git a/figs/step_lut_fast_jack_vel_fct_pos.pdf b/figs/step_lut_fast_jack_vel_fct_pos.pdf new file mode 100644 index 0000000..308f690 Binary files /dev/null and b/figs/step_lut_fast_jack_vel_fct_pos.pdf differ diff --git a/figs/step_lut_fast_jack_vel_fct_pos.png b/figs/step_lut_fast_jack_vel_fct_pos.png new file mode 100644 index 0000000..9ce6f07 Binary files /dev/null and b/figs/step_lut_fast_jack_vel_fct_pos.png differ diff --git a/figs/step_lut_filtered_errors_comp.pdf b/figs/step_lut_filtered_errors_comp.pdf new file mode 100644 index 0000000..7715d64 Binary files /dev/null and b/figs/step_lut_filtered_errors_comp.pdf differ diff --git a/figs/step_lut_filtered_errors_comp.png b/figs/step_lut_filtered_errors_comp.png new file mode 100644 index 0000000..a9ce356 Binary files /dev/null and b/figs/step_lut_filtered_errors_comp.png differ diff --git a/figs/step_lut_filtered_motion_comp.pdf b/figs/step_lut_filtered_motion_comp.pdf new file mode 100644 index 0000000..3537d85 Binary files /dev/null and b/figs/step_lut_filtered_motion_comp.pdf differ diff --git a/figs/step_lut_filtered_motion_comp.png b/figs/step_lut_filtered_motion_comp.png new file mode 100644 index 0000000..1b27474 Binary files /dev/null and b/figs/step_lut_filtered_motion_comp.png differ diff --git a/figs/step_lut_filters_bode_plot.pdf b/figs/step_lut_filters_bode_plot.pdf new file mode 100644 index 0000000..d1c2c1f Binary files /dev/null and b/figs/step_lut_filters_bode_plot.pdf differ diff --git a/figs/step_lut_filters_bode_plot.png b/figs/step_lut_filters_bode_plot.png new file mode 100644 index 0000000..7520016 Binary files /dev/null and b/figs/step_lut_filters_bode_plot.png differ diff --git a/figs/step_lut_obtained_lut.pdf b/figs/step_lut_obtained_lut.pdf new file mode 100644 index 0000000..f473d60 Binary files /dev/null and b/figs/step_lut_obtained_lut.pdf differ diff --git a/figs/step_lut_obtained_lut.png b/figs/step_lut_obtained_lut.png new file mode 100644 index 0000000..f22d811 Binary files /dev/null and b/figs/step_lut_obtained_lut.png differ diff --git a/figs/step_lut_remain_motion_remove_filtered.pdf b/figs/step_lut_remain_motion_remove_filtered.pdf new file mode 100644 index 0000000..28fab40 Binary files /dev/null and b/figs/step_lut_remain_motion_remove_filtered.pdf differ diff --git a/figs/step_lut_remain_motion_remove_filtered.png b/figs/step_lut_remain_motion_remove_filtered.png new file mode 100644 index 0000000..6f8981d Binary files /dev/null and b/figs/step_lut_remain_motion_remove_filtered.png differ diff --git a/figs/step_lut_schematic_principle.pdf b/figs/step_lut_schematic_principle.pdf new file mode 100644 index 0000000..0c16988 Binary files /dev/null and b/figs/step_lut_schematic_principle.pdf differ diff --git a/figs/step_lut_schematic_principle.png b/figs/step_lut_schematic_principle.png new file mode 100644 index 0000000..3e4341b Binary files /dev/null and b/figs/step_lut_schematic_principle.png differ diff --git a/figs/step_lut_spline_interpolation_lut.pdf b/figs/step_lut_spline_interpolation_lut.pdf new file mode 100644 index 0000000..fa09eb1 Binary files /dev/null and b/figs/step_lut_spline_interpolation_lut.pdf differ diff --git a/figs/step_lut_spline_interpolation_lut.png b/figs/step_lut_spline_interpolation_lut.png new file mode 100644 index 0000000..a714207 Binary files /dev/null and b/figs/step_lut_spline_interpolation_lut.png differ diff --git a/figs/trajectory_constant_bragg_velocity.pdf b/figs/trajectory_constant_bragg_velocity.pdf new file mode 100644 index 0000000..2de54a6 Binary files /dev/null and b/figs/trajectory_constant_bragg_velocity.pdf differ diff --git a/figs/trajectory_constant_bragg_velocity.png b/figs/trajectory_constant_bragg_velocity.png new file mode 100644 index 0000000..7de0474 Binary files /dev/null and b/figs/trajectory_constant_bragg_velocity.png differ diff --git a/figs/trajectory_constant_bragg_velocity_fj_velocity.pdf b/figs/trajectory_constant_bragg_velocity_fj_velocity.pdf new file mode 100644 index 0000000..cabcda3 Binary files /dev/null and b/figs/trajectory_constant_bragg_velocity_fj_velocity.pdf differ diff --git a/figs/trajectory_constant_bragg_velocity_fj_velocity.png b/figs/trajectory_constant_bragg_velocity_fj_velocity.png new file mode 100644 index 0000000..2720bfc Binary files /dev/null and b/figs/trajectory_constant_bragg_velocity_fj_velocity.png differ diff --git a/figs/trajectory_constant_fj_velocity.pdf b/figs/trajectory_constant_fj_velocity.pdf new file mode 100644 index 0000000..018f2ad Binary files /dev/null and b/figs/trajectory_constant_fj_velocity.pdf differ diff --git a/figs/trajectory_constant_fj_velocity.png b/figs/trajectory_constant_fj_velocity.png new file mode 100644 index 0000000..230927e Binary files /dev/null and b/figs/trajectory_constant_fj_velocity.png differ diff --git a/figs/trajectory_constant_fj_velocity_bragg_velocity.pdf b/figs/trajectory_constant_fj_velocity_bragg_velocity.pdf new file mode 100644 index 0000000..77b7fdb Binary files /dev/null and b/figs/trajectory_constant_fj_velocity_bragg_velocity.pdf differ diff --git a/figs/trajectory_constant_fj_velocity_bragg_velocity.png b/figs/trajectory_constant_fj_velocity_bragg_velocity.png new file mode 100644 index 0000000..5c3ff45 Binary files /dev/null and b/figs/trajectory_constant_fj_velocity_bragg_velocity.png differ