Commit 8e36cff3 authored by michael.kohnen's avatar michael.kohnen

Merge branch 'master' of https://git.rwth-aachen.de/ita/toolbox

parents dec646f0 5e2d2cd3
......@@ -106,7 +106,7 @@ ear_d = [-0.07 0.07];
W = sparse(diag(w)); % diagonal matrix containing weights
D = sparse(diag(dweights_rep)); % decomposition order-dependent Tikhonov regularization
Y = ita_sph_base(this.dirCoord,Nmax,'orthonormal',false); % calculate real-valued SHs using the measurement grid
Y = ita_sph_base(this.dirCoord,Nmax,'real'); % calculate real-valued SHs using the measurement grid
%% Calculate HRTF data for field points
if Nmax > 25
......@@ -131,7 +131,7 @@ for ear=1:2
% % calculate weighted SH coefficients using a decomposition order-dependent Tikhonov regularization
%
% freqData_temp = data.freqData;
% Y = ita_sph_base(data.channelCoordinates,Nmax,'orthonormal',false);
% Y = ita_sph_base(data.channelCoordinates,Nmax,'real');
a0 = (Y.'*W*Y + epsilon*D) \ Y.'*W * freqData_temp.';
%a0 = (Y.'*W*Y + epsilon*D) \ Y.' *
......@@ -142,10 +142,10 @@ for ear=1:2
% calculate range-extrapolated HRTFs
a1 = a0 .* hankel_rep.';
Yest = ita_sph_base(field,N,'orthonormal',false); % use real-valued SH's
Yest = ita_sph_base(field,N,'real'); % use real-valued SH's
hrtf_arbi(:,ear:2:end) = (Yest*a1).'; % interpolated + range-extrapolated HRTFs
else
Yest = ita_sph_base(field,Nmax,'orthonormal',false); % use real-valued SH's
Yest = ita_sph_base(field,Nmax,'real'); % use real-valued SH's
hrtf_arbi(:,ear:2:end) = (Yest*a0).'; % interpolated HRTFs
end
end
......
......@@ -1110,7 +1110,7 @@ classdef itaHRTF < itaAudio
W = diag(vWeights); % diagonal matrix containing weights
D = diag(regweights_rep); % decomposition order-dependent Tikhonov regularization
Y = ita_sph_base(this.dirCoord,Nmeas,'orthonormal',false); % calculate real-valued SHs using the measurement grid (high SH-order)
Y = ita_sph_base(this.dirCoord,Nmeas,'real'); % calculate real-valued SHs using the measurement grid (high SH-order)
%% Calculate spatially smoothed HRTF data set
hrtf_smoo_wo_ITD = zeros(this.nBins,2*this.dirCoord.nPoints); % init.: columns: LRLRLR...
......@@ -1302,11 +1302,11 @@ classdef itaHRTF < itaAudio
earSidePlot = sArgs.earSide;
if numel(phiC_deg)>1,
xData = phiC_deg;
strTitle =[ earSidePlot ' ear, \theta = ' num2str(round(thetaC_deg)) ''];
strTitle =[ earSidePlot ' ear, \theta = ' num2str(round(thetaC_deg)) ''];
strXlabel = '\phi in Degree';
else
xData = thetaC_deg;
strTitle =[earSidePlot ' ear, \phi = ' num2str(round(phiC_deg)) ''];
strTitle =[earSidePlot ' ear, \phi = ' num2str(round(phiC_deg)) ''];
strXlabel = '\theta in Degree';
end
......@@ -1394,11 +1394,11 @@ classdef itaHRTF < itaAudio
earSidePlot = sArgs.earSide;
if numel(phiC_deg)>1,
xData = phiC_deg;
strTitle =[ earSidePlot ' ear, \theta = ' num2str(round(thetaC_deg)) ''];
strTitle =[ earSidePlot ' ear, \theta = ' num2str(round(thetaC_deg)) ''];
strXlabel = '\phi in Degree';
else
xData = thetaC_deg;
strTitle =[earSidePlot ' ear, \phi = ' num2str(round(phiC_deg)) ''];
strTitle =[earSidePlot ' ear, \phi = ' num2str(round(phiC_deg)) ''];
strXlabel = '\theta in Degree';
end
......
......@@ -6,7 +6,7 @@ function [ data, samplerate, metadata ] = dfitaHRIRDAFFDataFunc( alpha, beta, it
% DAFF requires data alignment by multiple of 4
nResidual = mod( hrtf.nSamples, 4 );
data = [ hrtf.timeData', zeros( hrtf.nChannels, 4 - nResidual ) ];
data = [ hrtf.timeData', zeros( hrtf.nChannels, mod(4 - nResidual,4) ) ];
metadata = [];
end
......@@ -44,26 +44,33 @@ end
theta_start_deg = rad2deg( min( this.channelCoordinates.theta ) );
theta_end_deg = rad2deg( max( this.channelCoordinates.theta ) );
theta_num_elements = size( unique( this.channelCoordinates.theta ), 1 );
theta_num_elements = size( uniquetol( this.channelCoordinates.theta ), 1 );
phi_start_deg = rad2deg( min( mod( this.channelCoordinates.phi, 2*pi ) ) );
phi_end_deg = rad2deg( max( mod( this.channelCoordinates.phi, 2*pi ) ) );
phi_num_elements = size( unique( this.channelCoordinates.phi ), 1 );
phi_start_deg = rad2deg( min( mod( this.channelCoordinates.phi, 2 * pi ) ) );
phi_end_deg = rad2deg( max( mod( this.channelCoordinates.phi, 2 * pi ) ) );
phi_num_elements = size( uniquetol( this.channelCoordinates.phi ), 1 );
assert( phi_num_elements ~= 0 );
alphares = ( phi_end_deg - phi_start_deg ) / phi_num_elements; % phi end does not cover entire circle in this case
alphares_full_circle = ( phi_end_deg - phi_start_deg ) / ( phi_num_elements - 1 ); % phi end does not cover entire circle in this case
if phi_end_deg + alphares_full_circle >= 360.0
alpharange = [ phi_start_deg ( phi_end_deg + alphares_full_circle ) ]; % Account for full circle
alpharange = [ phi_start_deg 360 ]; % Account for full circle and force end of range to 360 deg
alphares = alphares_full_circle;
else
alpharange = [ phi_start_deg phi_end_deg ];
end
assert( alpharange( 1 ) >= 0.0 )
assert( alpharange( 2 ) <= 360.0 )
assert( theta_num_elements ~= 0 );
betares = ( theta_end_deg - theta_start_deg ) / ( theta_num_elements - 1 ); % phi end does not cover entire circle
betarange = 180 - [ theta_start_deg theta_end_deg ]; % Flip poles (DAFF starts at south pole)
assert( betarange( 2 ) >= 0.0 )
assert( betarange( 1 ) <= 180.0 )
%% Assemble metadata
metadata = daffv17_add_metadata( metadata, 'Generation script', 'String', 'writeDAFFFile.m' );
......
......@@ -14,6 +14,7 @@ classdef itaHpTF_Audio < itaHpTF
% Audio Engineering Society Convention 130, May 2011)
% normalized (Normalization of HpTF)
% smoothing (Smoothing bandwidth has to be defined in fractions of octaves, see also ita_smooth)
% mic (measured microphone transfer funcions - not inverted: length does not matter; will be adapted)
%
% itaHpTF_Audio Methods (private):
% HP_equalization If this.mic is not set, it will be unused
......@@ -30,7 +31,9 @@ classdef itaHpTF_Audio < itaHpTF
m_fUpper = 18000;
mMethod = 'mSTD';
mNormalized = true;
mGainComp = true;
mSmoothing = 1/6;
mSelectMeas = 1:8; % select the channels which should be used for the HpTF
end
properties(Dependent = true, Hidden = false)
......@@ -38,8 +41,10 @@ classdef itaHpTF_Audio < itaHpTF
fLower = 100;
fUpper = 18000;
method = 'mSTD';
normalized = true;
normalized = true; % normalization of the signal
gainComp = true; % microphone compensation
smoothing = 1/6;
selectMeas = 1:8; % select specific measurements
end
properties (Dependent = true, SetAccess = private)
......@@ -122,6 +127,13 @@ classdef itaHpTF_Audio < itaHpTF
function normalized = get.normalized(this)
normalized = this.mNormalized; end
function comp = get.gainComp(this)
comp = this.mGainComp; end
function sel = get.selectMeas(this)
sel = this.mSelectMeas; end
function smoothing = get.smoothing(this)
smoothing = this.mSmoothing; end
%% ................................................................
......@@ -151,6 +163,16 @@ classdef itaHpTF_Audio < itaHpTF
this = HP_equalization(this);
end
function this = set.selectMeas(this,ch)
this.mSelectMeas = ch;
this = HP_equalization(this);
end
function this = set.gainComp(this,comp)
this.mGainComp = comp;
this = HP_equalization(this);
end
function this = set.smoothing(this,smoothing)
this.mSmoothing = smoothing;
this = HP_equalization(this);
......@@ -162,11 +184,12 @@ classdef itaHpTF_Audio < itaHpTF
% SET PRIVATE
%..................................................................
function this = set.init(this,var)
this.nameHP = var.nameHP;
this.nameHP = var.nameHP;
this.nameMic = var.nameMic;
this.nameSubj = var.nameSubj;
this.repeat = var.repeat;
this.mTF.time = var.time;
this.selectMeas = 1:var.repeat;
this = HP_equalization(this);
end
......@@ -175,11 +198,8 @@ classdef itaHpTF_Audio < itaHpTF
% Audio Engineering Society Convention 130, May 2011
tWin = this.TF.trackLength; % crop HPTF
if this.mic.dimensions == 2 % mic min phase + extension
minMic = ita_minimumphase(this.mic);
[mic, TF] = ita_extend_dat(minMic,this.TF);
else TF = this.TF;
end
measSel = sort([2*this.selectMeas-1 2*this.selectMeas]);
TF = this.TF.ch(measSel);
%init
thisEQ = this;
......@@ -200,14 +220,19 @@ classdef itaHpTF_Audio < itaHpTF
otherwise
error('Unknown type');
end
if this.mic.dimensions == 2
Rec = ita_multiply_spk(Rec,mic);
if this.mic.dimensions == 2 % Compensation of mic
minMic = ita_minimumphase(this.mic);
RecM = ita_convolve(Rec,minMic.ch(cdx));
RecM.fftDegree = TF.fftDegree;
else
RecM = Rec;
end
%% Short Filter with no correction for low freqs and minimun phase
aux = max(abs(Rec.freqData),[],2);
%% Short Filter with no correction for low freqs and minimum phase
aux = max(abs(RecM.freqData),[],2);
% find first maximum and truncate low freq correction at this point
idxDF = Rec.freq2index([this.fLower this.fLower*1.5 ]);
idxDF = RecM.freq2index([this.fLower this.fLower*1.5 ]);
d_aux = diff(aux(idxDF(1):idxDF(2)));
idx = find(diff(sign(d_aux)) ~= 0,1,'first'); % Bruno style...
aux(1:idxDF(1)+idx+1) = aux(idxDF(1)+idx+2);
......@@ -227,10 +252,18 @@ classdef itaHpTF_Audio < itaHpTF
this_min = ita_minimumphase(ita_time_shift(HpTF,tWin/2));
this_win = ita_time_window(this_min,[tWin*0.99,tWin],'time','crop');
if this.normalized,
this_norm = ita_normalize_dat(this_win);
if this.gainComp % compensate gains from mics (equalize)
idxDF = this_win.freq2index(this.fLower);
chGain = 20*log10(abs(this_win.freqData(idxDF,:)));
this_comp = this_win;
this_comp.freqData = bsxfun(@times,this_win.freqData,10.^(-chGain/20));
else, this_comp = this_win;
end
if this.normalized
this_norm = ita_normalize_dat(this_comp);
thisEQ.timeData = this_norm.timeData;
else thisEQ.timeData = this_win.timeData;
else, thisEQ.timeData = this_comp.timeData;
end
if ~isempty(this.savePath)
......
......@@ -88,6 +88,7 @@ classdef itaHpTF_MS < itaHpTF
% Measure Right side
MS.inputChannels = chIn(2);
MS.outputChannels = chOut(2);
commandwindow
resultR = MS.run;
resultR.channelNames{1} = strR;
......@@ -108,7 +109,7 @@ classdef itaHpTF_MS < itaHpTF
disp(['Measurement ',num2str(idxM),'/',num2str(this.repeat),' finished.'])
disp('Put headphones off and on again. Press any key to continue.')
pause
pause(2)
pause(1)
else
commandwindow
fprintf('\nMEASUREMENT DONE!\n')
......@@ -118,6 +119,7 @@ classdef itaHpTF_MS < itaHpTF
MS.inputChannels = chIn;
HpTF = itaHpTF_Audio(this);
HpTF.selectMeas = 1:this.repeat;
assignin('base', ['HpTF_' this.nameSubj], HpTF)
end
......
......@@ -40,7 +40,8 @@ ignoreList = {'.svn', ...
'doc', ...
'GuiCallbacks', ...
'external_packages', ...
'ExternalPackages'};
'ExternalPackages', ...
'helpers'};
pathStr = genpath(sArgs.rootpath);
prefixToolbox = fliplr(strtok(fliplr(sArgs.rootpath),filesep)); %get Toolbox folder name
......
......@@ -142,7 +142,7 @@ classdef itaMotorControlNanotec < itaMotorControl
% parse the notfound options for wait
[controlOptions, notFound] = ita_parse_arguments(controlOptions,notFound);
this.wait = controlOptions.wait;
for index = 1:length(this.motorList)
motorposition = sArgs.(this.motorList{index}.getMotorName());
this.started(index) = this.motorList{index}.prepareMove(motorposition,notFound{:});
......@@ -222,6 +222,15 @@ classdef itaMotorControlNanotec < itaMotorControl
ita_verbose_info('Finished preparing',2)
end
function startMove(this)
for index = 1:length(this.motorList)
if this.started(index)
this.motorList{index}.startMoveToPosition();
end
end
this.wait4everything;
end
function startContinuousMoveNow(this)
% start moves
for index = 1:length(this.motorList)
......@@ -235,6 +244,7 @@ classdef itaMotorControlNanotec < itaMotorControl
this.mIsInitialized = false;
error(sprintf('Motor %s is not responding!',this.motorList{index}.getMotorName));
end
this.wait4everything
this.preparedList = [];
end
......@@ -447,7 +457,7 @@ classdef itaMotorControlNanotec < itaMotorControl
else
ita_verbose_info('Position NOT reached! - Check for errors!', 0);
this.send_commandlist(this.failed_command_repititions); % mpo: bugfix: send_commandlist needs argument
this.isReferenced = false;
% this.isReferenced = false;
end
this.clear_receivedlist;
this.started(1:length(this.motorIDList)) = false;
......
......@@ -14,18 +14,25 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
end
properties(Constant, Hidden = true)
sArgs_default_motor = struct( ...
'wait', true, ...
'speed', 2, ...
'VST', 'adaptiv', ...
'limit', true, ...
'continuous', false, ...
'absolut', true, ...
'closed_loop', false, ...
'acceleration_ramp', 1, ...
'gear_ratio', 5, ...
'current', 100, ...
'ramp_mode', 2 );
'wait', true, ...
'speed', 2, ...
'VST', 'adaptiv', ...
'limit', true, ...
'continuous', false, ...
'absolut', true, ...
'closed_loop', false, ...
'acceleration_ramp',1, ...
'gear_ratio', 5, ...
'current', 100, ...
'ramp_mode', 2, ...
'P', 400, ...
'I', 2.0, ...
'D', 700, ...
'P_nenner', 3, ...
'I_nenner', 5,...
'D_nenner', 3);
end
methods
......@@ -87,11 +94,11 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
% phasenstrom im stillstand
motorControl.add_to_commandlist(sprintf('#%dr=0\r' , this.motorID));
% fehlerkorrekturmodus
motorControl.add_to_commandlist(sprintf('#%dU=1\r' , this.motorID));
motorControl.add_to_commandlist(sprintf('#%dU=0\r' , this.motorID));
% ausschwingzeit
motorControl.add_to_commandlist(sprintf('#%dO=1\r' , this.motorID));
% umkehrspiel
motorControl.add_to_commandlist(sprintf('#%dz=0\r' , this.motorID));
motorControl.add_to_commandlist(sprintf('#%dz=5\r' , this.motorID));
% automatisches senden des status deaktivieren
motorControl.add_to_commandlist(sprintf('#%dJ=0\r' , this.motorID));
......@@ -125,7 +132,7 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
motorControl.add_to_commandlist(sprintf('#%dd=1\r' , this.motorID));
% Calculate and set lower speed:
% stepspersecond = round(this.sArgs_default_motor.speed/0.9*this.sArgs_default_motor.gear_ratio);
motorControl.add_to_commandlist(sprintf('#%du=%d\r' , this.motorID, 3));
motorControl.add_to_commandlist(sprintf('#%du=%d\r' , this.motorID, 1));
% Calculate and set upper speed:
stepspersecond = round(this.sArgs_default_motor.speed/0.9*this.sArgs_default_motor.gear_ratio);
motorControl.add_to_commandlist(sprintf('#%do=%d\r' , this.motorID, stepspersecond));
......@@ -149,7 +156,7 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
sArgs = ita_parse_arguments(sArgs,varargin);
end
if sArgs.continuous
ret = this.prepare_move(position, 'speed', sArgs.speed,'continuous', true);
ret = this.prepare_move(position, sArgs);
started = true;
else
% if only the phi angle is given
......@@ -300,19 +307,25 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
% Activate CL during movement:
motorControl.add_to_commandlist(sprintf('#%d:CL_enable=2\r' , this.motorID));
% Nice values for the speed closed loop control:
pos = [0.5 1 2 3 4 8 12 16 25 32 40 50];
vecP = [0.5 1.5 2.5 3.5 4.5 4.5 5.5 2.5 2.0 1.3 1.3 1.3];
vecI = [0.05 0.1 0.2 0.3 0.4 0.8 1.2 1.6 2.0 2.5 2.5 2.5];
vecD = [9 6 4 3 2 1 1 3 6 10 10 10];
pP = polyfit(pos,vecP,5);
pI = polyfit(pos,vecI,5);
pD = polyfit(pos,vecD,5);
P = polyval(pP,this.sArgs_motor.speed);
I = polyval(pI,this.sArgs_motor.speed);
D = polyval(pD,this.sArgs_motor.speed);
P_nenner = 5;
I_nenner = 5;
D_nenner = 5;
% pos = [0.5 1 2 3 4 8 12 16 25 32 40 50];
% vecP = [0.5 1.5 2.5 3.5 4.5 4.5 5.5 2.5 2.0 1.3 1.3 1.3];
% vecI = [0.05 0.1 0.2 0.3 0.4 0.8 1.2 1.6 2.0 2.5 2.5 2.5];
% vecD = [9 6 4 3 2 1 1 3 6 10 10 10];
% pP = polyfit(pos,vecP,5);
% pI = polyfit(pos,vecI,5);
% pD = polyfit(pos,vecD,5);
% P = polyval(pP,this.sArgs_motor.speed);
% I = polyval(pI,this.sArgs_motor.speed);
% D = polyval(pD,this.sArgs_motor.speed);
% P_nenner = 5;
% I_nenner = 5;
% D_nenner = 5;
P = this.sArgs_motor.P;% (400 = default)
I = this.sArgs_motor.I;% (2 = default)
D = this.sArgs_motor.D;% (700 = default)
P_nenner = this.sArgs_motor.P_nenner;
I_nenner = this.sArgs_motor.I_nenner;
D_nenner = this.sArgs_motor.D_nenner;
P_zaehler = round(P*2^P_nenner);
I_zaehler = round(I*2^I_nenner);
D_zaehler = round(D*2^D_nenner);
......@@ -322,13 +335,14 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
motorControl.add_to_commandlist(sprintf('#%d:CL_KI_v_N=%d\r' , this.motorID, I_nenner));
motorControl.add_to_commandlist(sprintf('#%d:CL_KD_v_Z=%d\r' , this.motorID, D_zaehler));
motorControl.add_to_commandlist(sprintf('#%d:CL_KD_v_N=%d\r' , this.motorID, D_nenner));
% Nice values for the positioning closed loop control:
P = 200;% (400 = default)
I = 1.0;% (2 = default)
D = 300;% (700 = default)
P_nenner = 3;
I_nenner = 5;
D_nenner = 3;
% % Nice values for the positioning closed loop control:
P = this.sArgs_motor.P;% (400 = default)
I = this.sArgs_motor.I;% (2 = default)
D = this.sArgs_motor.D;% (700 = default)
P_nenner = this.sArgs_motor.P_nenner;
I_nenner = this.sArgs_motor.I_nenner;
D_nenner = this.sArgs_motor.D_nenner;
P_zaehler = round(P*2^P_nenner);
I_zaehler = round(I*2^I_nenner);
D_zaehler = round(D*2^D_nenner);
......@@ -338,6 +352,7 @@ classdef itaMotorNanotec_HRTFarc < itaMotorNanotec
motorControl.add_to_commandlist(sprintf('#%d:CL_KI_s_N=%d\r' , this.motorID, I_nenner));
motorControl.add_to_commandlist(sprintf('#%d:CL_KD_s_Z=%d\r' , this.motorID, D_zaehler));
motorControl.add_to_commandlist(sprintf('#%d:CL_KD_s_N=%d\r' , this.motorID, D_nenner));
% Kask V-Regler: P = 1.2, I = 0.85, D = 0.7
% Kask- P-Regler: P = 400 (default), I = 2 (default), D = 700 (default)
% TODO: Send values to the motor... or we just skip the
......
......@@ -204,7 +204,7 @@ classdef test_itaEimarMotorControl < itaMeasurementTasksScan
% calculate the pre angle
% the pre angle is needed because the measurement setup will
% not start recording imidiately
numRepetitions = this.measurementSetup.repititions;
numRepetitions = this.measurementSetup.repetitions;
timePerRepetition = this.measurementSetup.twait*length(this.measurementSetup.outputChannels);
speed = 360/(numRepetitions*timePerRepetition);
......@@ -215,7 +215,7 @@ classdef test_itaEimarMotorControl < itaMeasurementTasksScan
preAngle = min(preAngle,15);
preAngle = max(preAngle,8);
numTotalRepetitions = numRepetitions+ceil(preAngleTime/(timePerRepetition))+9;
this.measurementSetup.repititions = numTotalRepetitions;
this.measurementSetup.repetitions = numTotalRepetitions;
%prepare motors for continuous measurement
this.mMotorControl.prepareForContinuousMeasurement('speed',speed,'preAngle',preAngle);
......
......@@ -553,7 +553,7 @@ classdef itaOptitrack < handle
if Optitrack_obj.singleShot
Optitrack_obj.timerData = timer('TimerFcn',{@Optitrack_obj.TimerCallback},'ExecutionMode','singleShot'); % execute timer callback once
else
Optitrack_obj.timerData = timer('TimerFcn',{@Optitrack_obj.TimerCallback},'Period',round(1/16/Optitrack_obj.frameRate*1000)/1000,'ExecutionMode','fixedRate','BusyMode','drop');
Optitrack_obj.timerData = timer('TimerFcn',{@Optitrack_obj.TimerCallback},'Period',round(1/16/Optitrack_obj.frameRate*1000)/1000,'ExecutionMode','fixedSpacing','BusyMode','drop');
end
else
Optitrack_obj.correctRowIdx = 1; % reset row counter
......@@ -561,7 +561,7 @@ classdef itaOptitrack < handle
Optitrack_obj.timerData = timer('TimerFcn',{@Optitrack_obj.TimerCallback},'ExecutionMode','singleShot'); % execute timer callback once
else
Optitrack_obj.timerData = timer('TimerFcn',{@Optitrack_obj.TimerCallback},'Period',round(1/16/Optitrack_obj.frameRate*1000)/1000,...
'ExecutionMode','fixedRate','BusyMode','drop','TasksToExecute',32*Optitrack_obj.numFrames); % execute timer 16*Optitrack_obj.numFrames times but abort as soon as Optitrack_obj.rigidBodyLogData.data is filled
'ExecutionMode','fixedSpacing','BusyMode','drop','TasksToExecute',32*Optitrack_obj.numFrames); % execute timer 16*Optitrack_obj.numFrames times but abort as soon as Optitrack_obj.rigidBodyLogData.data is filled
end
end
......
......@@ -52,8 +52,15 @@ if abs(dot(v,u,2)) > 1e-5
end
% normalize view/up vectors
v = normr(v);
u = normr(u);
[~,colv]=size(v);
[~,colu]=size(u);
if (colv == 1)
v(~isnan(v(:,1)),:) = v(~isnan(v(:,1)),:) ./ abs(v(~isnan(v(:,1)),:));
u(~isnan(u(:,1)),:) = u(~isnan(u(:,1)),:) ./ abs(u(~isnan(u(:,1)),:));
else
v = sqrt( ones ./ (sum((v(~isnan(v(:,1)),:).*v(~isnan(v(:,1)),:))')) )' * ones(1,colv).*v(~isnan(v(:,1)),:);
u = sqrt( ones ./ (sum((u(~isnan(u(:,1)),:).*u(~isnan(u(:,1)),:))')) )' * ones(1,colu).*u(~isnan(u(:,1)),:);
end
% calculate side vector
s = cross(v, u);
......@@ -65,7 +72,7 @@ qx = qw;
qy = qw;
qz = qw;
for idx = 1:vec_ent;
for idx = 1:vec_ent
% build rotation matrix
R = [s(idx,:); u(idx,:); -v(idx,:)];
......
......@@ -63,8 +63,15 @@ if abs(dot(v,u,2)) > 1e-5
end
% normalize view/up vectors
v(~isnan(v(:,1)),:) = normr(v(~isnan(v(:,1)),:));
u(~isnan(u(:,1)),:) = normr(u(~isnan(u(:,1)),:));
[~,colv]=size(v);
[~,colu]=size(u);
if (colv == 1)
v(~isnan(v(:,1)),:) = v(~isnan(v(:,1)),:) ./ abs(v(~isnan(v(:,1)),:));
u(~isnan(u(:,1)),:) = u(~isnan(u(:,1)),:) ./ abs(u(~isnan(u(:,1)),:));
else
v = sqrt( ones ./ (sum((v(~isnan(v(:,1)),:).*v(~isnan(v(:,1)),:))')) )' * ones(1,colv).*v(~isnan(v(:,1)),:);
u = sqrt( ones ./ (sum((u(~isnan(u(:,1)),:).*u(~isnan(u(:,1)),:))')) )' * ones(1,colu).*u(~isnan(u(:,1)),:);
end
% init.
y = NaN(size(v,1),1);
......
......@@ -114,7 +114,7 @@ classdef itaMSTF < itaMSPlaybackRecord
fieldName = fieldnames(rmfield(this.saveobj,'dateSaved'));
end
for ind = 1:numel(fieldName);
for ind = 1:numel(fieldName)
try
this.(fieldName{ind}) = varargin{1}.(fieldName{ind});
catch errmsg
......@@ -371,11 +371,10 @@ classdef itaMSTF < itaMSPlaybackRecord
%% sweep rate from analytic calculation, only using sweep parameters / PDI
nSamples = ita_nSamples( this.fftDegree );
finalFreqRange = this.finalFreqRange;
% MMT: use nSamples-1 here to be conform with sweep calculation
% based on timeVector and chirp function
finalExcitationLength = (nSamples-1)/this.samplingRate - this.stopMargin;
sweepRate(1) = log2(finalFreqRange(2)/finalFreqRange(1))/finalExcitationLength;
sweepRate(1) = log2(this.finalFreqRange(2)/this.finalFreqRange(1))/finalExcitationLength;
%% sweep rate of analysis of excitation signal
sweepRate(2) = ita_sweep_rate(this.raw_excitation,[2000 this.samplingRate/3]);
......@@ -563,7 +562,7 @@ classdef itaMSTF < itaMSPlaybackRecord