Stuck at upsampling trajectory data to higher sampling frequency - shift
6 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Hi all,
I am trying to upsample some trajectory data from my motion capture dataset (500Hz) to match my sensor dataset (5000Hz). To obtain the sensordata frame that would correspond to a specific motion capture frame, let's say, 31, I am doing 31 * (5000/500) - 9 (or (31-1)*10 + 1 would work, too). I obtained the following code from a supervisor(who is not available the coming weeks) and I tweaked it a bit because I found some errors. But recently I found that the trajectory data shifts negatively, so for marker Fc (x position), the original position at frame 1 is 0 (in the motion capture dataset), but in the interpolated data at frame 1 it is minus something. And this is also the case for the last frame.
This is my complete code, but I am having trouble with the interpolate_moca() function. The plots below illustrate what I mean. Thanks in advance for taking a look at it with me!
l = load("C:\Users\puckb\Documents\Study\2024-2025\Graduation\Graduation\4Results\Code\Fietskar-dataprocessing-20250618\Fietskar-dataprocessing-20250618\01-matfiles\anal_general_20250729120951.mat");
file_anal = l.file_anal;
S = l.S;
M = l.M;
t = 47; % Trial number
i_mstart_t = file_anal.start_index_x(t);
i_mend_t = file_anal.stop_index_x(t);
i_sstart_t = (i_mstart_t*10) - 9; % convert start index to sensor frame
i_send_t = (i_mend_t*10) - 9; % convert stop index to sensor frame
i_Iend_t = i_send_t - i_sstart_t + 1;
time = dm.time(i_mstart_t:i_mend_t);
time_s = ds.Time(i_sstart_t:i_send_t);
fco_moca_forICOR = 30; % Filter cut-off frequency (Hz) used to refilter the fitted spline used to interpolate the moca data.
% Trial specifics
trial_name = file_anal.filename_moca{t}; trial_label = trial_name(1:end-4);
dm = M.(trial_label);
ds = S.(trial_label);
labels = dm.labels;
Fc_nam = 'Fc';
Fc_id = find(strcmp(labels, Fc_nam));
disp(Fc_id);
fs_sens = 5000;
fs_moca = 500;
% Interpolating trajectory
traj_all = dm.trajectories;
traj = traj_all(:,:,i_mstart_t:i_mend_t);
traj_intp = interpolate_moca(traj,time,time_s,fs_sens,fs_moca,fco_moca_forICOR);
% Trajectory original Fc x en z
%not interpolated
F_glob_x = squeeze(dm.trajectories(Fc_id, 1, i_mstart_t:i_mend_t));
F_glob_y = squeeze(dm.trajectories(Fc_id, 2, i_mstart_t:i_mend_t));
F_glob_z = squeeze(dm.trajectories(Fc_id, 3, i_mstart_t:i_mend_t));
% Interpolated
Fc_x_int = squeeze(traj_intp(Fc_id, 1,:)); % Get arrays for x, y, z trajectories of desired markers,
Fc_y_int = squeeze(traj_intp(Fc_id, 2,:)); % between start and stop frames for sensor (calculated
Fc_z_int = squeeze(traj_intp(Fc_id, 3,:)); % based on moca startstop indices
% Plotting
f = figure;
subplot(2,1,1);
plot(F_glob_x,F_glob_z);
subplot(2,1,2);
plot(Fc_x_int,Fc_z_int);
function traj_intp = interpolate_moca(traj,time,time_s,fs_sens,fs_moca,fco_moca_forICOR)
% Interpolate data
r = fs_sens/fs_moca; % Sample rate increase factor, must be multiplied with moca frames, and then -9
traj_intp = nan(size(traj,1),size(traj,2),((r*size(traj,3))-9)); % PUCK EDIT changed r*size(traj,3) into ((r*size(traj,3))-9)
traj_og = traj;
Fc_x_int = squeeze(traj(Fc_id, 1,:)); % Get arrays for x, y, z trajectories of desired markers,
disp([time(1), time(end)]);
disp([time_s(1), time_s(end)]);
for mar = 1:size(traj,1)
% Get trajectory data
xd_og = squeeze(traj(mar,1,:));
yd_og = squeeze(traj(mar,2,:));
zd_og = squeeze(traj(mar,3,:));
ns = size(xd_og,1); %number of samples
ins = (r*ns)-9; % interpolated number of samples
% Corresponding timevector
t_og = time;
%t_in = interp(t_og,r);
t_in = time_s; % PUCK EDIT added actual timevector of sensordata, of course trimmed between startstop
% Find nans
xxnan = double(isnan(xd_og));
yynan = double(isnan(yd_og));
zznan = double(isnan(zd_og));
% xyznan = [xxnan,yynan,zznan];
xxnan_in = interp1(t_og, xxnan,t_in,'linear');
yynan_in = interp1(t_og, yynan,t_in,'linear');
zznan_in = interp1(t_og, zznan,t_in,'linear');
xyznan_in = [xxnan_in,yynan_in,zznan_in];
xyznan_in(xyznan_in<=0.4) = 0;
xyznan_in(xyznan_in>0.4) = 1;
% For these, linearly interpolate where the nans were. We will be replacing these by nans again later,
% but we cannot interpolate with duplicates in the query vector
xd = fillmissing(xd_og,"pchip");
yd = fillmissing(yd_og,"pchip");
zd = fillmissing(zd_og,"pchip");
% Interpolate
xx = interpft(xd,ins); % PUCK EDIT replaced r*ns by ins
yy = interpft(yd,ins); % PUCK EDIT replaced r*ns by ins
zz = interpft(zd,ins); % PUCK EDIT replaced r*ns by ins
% Add NaNs back in
xx((xyznan_in(:,1))==1) = NaN;
yy((xyznan_in(:,2))==1) = NaN;
zz((xyznan_in(:,3))==1) = NaN;
% Refilter: These will be used to determine the ICOR, so we filter them with a low threshold, otherwise we will get all-over-the-place estimates for the ICOR
xx = filt_moca(xx, fco_moca_forICOR, fs_sens);
yy = filt_moca(yy, fco_moca_forICOR, fs_sens);
zz = filt_moca(zz, fco_moca_forICOR, fs_sens);
% Add into complete trajectory (stored variable)
traj_intp(mar,1:3,:) = [xx;yy;zz];
end
end
function filtered_traj = filt_moca(traj, fco_moca, fs_moca)
% Filters the motion capture data using cutoff frequency
% Filter inputs: 6th order butterworth filter results in 12th order filter
[B,A] = butter(6, (fco_moca/(fs_moca/2)), 'low');
nan_is = isnan(traj);
not_nan_is = ~isnan(traj);
x_og_nonan = traj(not_nan_is);
x_nonan = filtfilt(B,A, x_og_nonan);
x = traj; x(not_nan_is) = x_nonan;
filtered_traj = x';
end

5 Commenti
Meg Noah
il 11 Ago 2025
Stineman interpolation is a good smooth operation as well: https://www.mathworks.com/matlabcentral/fileexchange/104195-smooth-operator-stineman-1d-interpolation
Risposte (0)
Vedere anche
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
