Stuck at upsampling trajectory data to higher sampling frequency - shift

2 Ansichten (letzte 30 Tage)
Puck
Puck am 30 Jul. 2025
Kommentiert: Meg Noah am 11 Aug. 2025
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 Kommentare

Melden Sie sich an, um zu kommentieren.

Antworten (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by