I'm running a MATLAB script on macOS that performs sensor fusion using GNSS and IMU data. The script runs perfectly in MATLAB R2024 but fails in MATLAB R2022 with the following error during the ECEF to ECI frame transformation:
=== Task 5: ECI and ECEF Frame Plotting ===
Error using *
Incorrect dimensions for matrix multiplication. Check that the number of columns in the
first matrix matches the number of rows in the second matrix. To operate on each element
of the matrix individually, use TIMES (.*) for elementwise multiplication.
Error in untitled3>transform_ecef_to_eci_gnss (line 332)
pos_eci(i,:)= (Rz* pos_ecef(i,:).').';
Error in untitled3 (line 121)
transform_ecef_to_eci_gnss(T_gnss, EARTH_ROTATION_RATE);
I suspect there might be differences between MATLAB R2022 and R2024 that affect this function. I've confirmed that all required files and dependencies are present and that the MATLAB path is set correctly in both environments.
Below is the relevant portion of my code:
function Fusion_ECI_Corrected()
% FUSION_ECI_CORRECTED
% Enhanced GNSS and IMU Fusion in ECI Frame with Corrected Gravity Compensation and Drift Correction,
% using load_nav_data().
%% Task 0: Configuration
[IMU_Data, GNSS_Data, fsIMU, fsGNSS] = load_nav_data();
T_imu = struct2table(IMU_Data);
T_gnss = struct2table(GNSS_Data);
% Rename velocity fields if necessary
if ismember('Velocity_X', T_gnss.Properties.VariableNames)
T_gnss.Properties.VariableNames{'Velocity_X'} = 'VX_ECEF_mps';
end
if ismember('Velocity_Y', T_gnss.Properties.VariableNames)
T_gnss.Properties.VariableNames{'Velocity_Y'} = 'VY_ECEF_mps';
end
if ismember('Velocity_Z', T_gnss.Properties.VariableNames)
T_gnss.Properties.VariableNames{'Velocity_Z'} = 'VZ_ECEF_mps';
end
% Constants
EARTH_ROTATION_RATE = 7.2921159e-5;
% (Other constants and processing steps...)
%% Task 5: ECI and ECEF Transform & Plot
fprintf('\n=== Task 5: ECI and ECEF Transform & Plot ===\n');
[pos_eci_gnss, vel_eci_gnss, acc_eci_gnss, ...
pos_ecef_gnss, vel_ecef_gnss, acc_ecef_gnss] = transform_ecef_to_eci_gnss(T_gnss, EARTH_ROTATION_RATE);
% (Rest of the code for storing and plotting data)
end
function [pos_eci, vel_eci, acc_eci, pos_ecef, vel_ecef, acc_ecef] = transform_ecef_to_eci_gnss(T_gnss, EARTH_ROTATION_RATE)
t_rel = T_gnss.Posix_Time - T_gnss.Posix_Time(1);
theta = -EARTH_ROTATION_RATE .* t_rel;
cos_t = cos(theta);
sin_t = sin(theta);
pos_ecef = [T_gnss.X_ECEF_m, T_gnss.Y_ECEF_m, T_gnss.Z_ECEF_m];
vel_ecef = [T_gnss.VX_ECEF_mps, T_gnss.VY_ECEF_mps, T_gnss.VZ_ECEF_mps];
n = length(theta);
pos_eci = zeros(n, 3);
vel_eci = zeros(n, 3);
for i = 1:n
Rz = [cos_t(i), -sin_t(i), 0;
sin_t(i), cos_t(i), 0;
0, 0, 1];
pos_eci(i, :) = (Rz * pos_ecef(i, :)').';
vel_eci(i, :) = (Rz * vel_ecef(i, :)').';
end
dt = mean(diff(T_gnss.Posix_Time));
acc_eci = zeros(n, 3);
acc_ecef = zeros(n, 3);
for i = 2:n
acc_eci(i, :) = (vel_eci(i, :) - vel_eci(i-1, :)) / dt;
acc_ecef(i, :) = (vel_ecef(i, :) - vel_ecef(i-1, :)) / dt;
end
acc_eci(1, :) = acc_eci(2, :);
acc_ecef(1, :) = acc_ecef(2, :);
end
Here is the load_nav_data function :
function [IMU_Data, GNSS_Data, fsIMU, fsGNSS] = load_nav_data()
% LOAD_NAV_DATA Loads IMU and GNSS data from files.
%
% [IMU_Data, GNSS_Data, fsIMU, fsGNSS] = load_nav_data()
%
% - IMU data is read from a .dat file (without header) and is expected to
% have 10 columns in the order:
% Message_Counter, Sample_Time, Gyro_X, Gyro_Y, Gyro_Z,
% Accel_X, Accel_Y, Accel_Z, Temperature, Status.
%
% - GNSS data is read from a .csv file (with one header row). The file is
% assumed to have 20 columns with the following order:
% 1) UTC_yyyy
% 2) UTC_MM
% 3) UTC_dd
% 4) UTC_HH
% 5) UTC_mm
% 6) UTC_ss
% 7) Posix_Time
% 8) Latitude_deg
% 9) Longitude_deg
% 10) Height_deg (stored as Height_m)
% 11) X_ECEF_m
% 12) Y_ECEF_m
% 13) Z_ECEF_m
% 14) VX_ECEF_mps -> Velocity_X
% 15) VY_ECEF_mps -> Velocity_Y
% 16) VZ_ECEF_mps -> Velocity_Z
% 17) HDOP
% 18) VDOP
% 19) PDOP
% 20) TDOP
%
% The function also prompts for the IMU and GNSS sampling frequencies.
%
% Author: Your Name
% Date: YYYY-MM-DD
%% Select IMU Data File (.dat, no header)
[imuFile, imuPath] = uigetfile('*.dat', 'Select IMU file (.dat format)');
if isequal(imuFile, 0)
error('No IMU file selected.');
end
imuFullFile = fullfile(imuPath, imuFile);
imuRaw = readmatrix(imuFullFile);
if size(imuRaw,2) ~= 10
error('IMU data must have exactly 10 columns.');
end
% Build IMU_Data structure (each field as a 1xN row vector)
IMU_Data.Message_Counter = imuRaw(:,1).';
IMU_Data.Sample_Time = imuRaw(:,2).';
IMU_Data.Gyro_X = imuRaw(:,3).';
IMU_Data.Gyro_Y = imuRaw(:,4).';
IMU_Data.Gyro_Z = imuRaw(:,5).';
IMU_Data.Accel_X = imuRaw(:,6).';
IMU_Data.Accel_Y = imuRaw(:,7).';
IMU_Data.Accel_Z = imuRaw(:,8).';
IMU_Data.Temperature = imuRaw(:,9).';
IMU_Data.Status = imuRaw(:,10).';
%% Select GNSS Data File (.csv)
[gnssFile, gnssPath] = uigetfile('*.csv', 'Select GNSS file (.csv format)');
if isequal(gnssFile, 0)
error('No GNSS file selected.');
end
gnssFullFile = fullfile(gnssPath, gnssFile);
% Read GNSS file, skipping the header row (assumes one header row)
GNSS_raw = readmatrix(gnssFullFile, 'NumHeaderLines', 1);
if size(GNSS_raw,2) ~= 20
error('GNSS data must have exactly 20 columns.');
end
% Build GNSS_Data structure using fixed column indices.
GNSS_Data.UTC_yyyy = GNSS_raw(:,1).';
GNSS_Data.UTC_MM = GNSS_raw(:,2).';
GNSS_Data.UTC_dd = GNSS_raw(:,3).';
GNSS_Data.UTC_HH = GNSS_raw(:,4).';
GNSS_Data.UTC_mm = GNSS_raw(:,5).';
GNSS_Data.UTC_ss = GNSS_raw(:,6).';
GNSS_Data.Posix_Time = GNSS_raw(:,7).';
GNSS_Data.Latitude_deg = GNSS_raw(:,8).';
GNSS_Data.Longitude_deg = GNSS_raw(:,9).';
% Although the header is Height_deg, we store it as Height_m here.
GNSS_Data.Height_m = GNSS_raw(:,10).';
GNSS_Data.X_ECEF_m = GNSS_raw(:,11).';
GNSS_Data.Y_ECEF_m = GNSS_raw(:,12).';
GNSS_Data.Z_ECEF_m = GNSS_raw(:,13).';
GNSS_Data.Velocity_X = GNSS_raw(:,14).';
GNSS_Data.Velocity_Y = GNSS_raw(:,15).';
GNSS_Data.Velocity_Z = GNSS_raw(:,16).';
GNSS_Data.HDOP = GNSS_raw(:,17).';
GNSS_Data.VDOP = GNSS_raw(:,18).';
GNSS_Data.PDOP = GNSS_raw(:,19).';
GNSS_Data.TDOP = GNSS_raw(:,20).';
%% Prompt user for sampling frequencies
prompt = {'Enter IMU Sampling Frequency (Hz):', 'Enter GNSS Sampling Frequency (Hz):'};
answer = inputdlg(prompt, 'Sampling Frequencies', [1 50], {'400','10'});
if isempty(answer)
error('Sampling frequency input cancelled.');
end
fsIMU = str2double(answer{1});
fsGNSS = str2double(answer{2});
if isnan(fsIMU) || isnan(fsGNSS) || fsIMU <= 0 || fsGNSS <= 0
error('Invalid sampling frequencies.');
end
%% Save sampling frequencies for future use.
SAMPLE_FREQ = fsIMU;
GNSS_FREQ = fsGNSS;
save('sampling_frequencies.mat', 'SAMPLE_FREQ', 'GNSS_FREQ');
disp(['IMU Sampling Frequency: ' num2str(SAMPLE_FREQ) ' Hz']);
disp(['GNSS Sampling Frequency: ' num2str(GNSS_FREQ) ' Hz']);
end
What I've Tried:
- Verified that all file paths and dependencies are correct in both MATLAB R2022 and R2024.
- Reviewed MATLAB’s documentation for any changes related to matrix multiplication or file I/O between versions.
My Question:
Has anyone encountered similar version-specific issues with matrix multiplication in MATLAB? Are there known changes between MATLAB R2022 and R2024 that could cause this error in the transform_ecef_to_eci_gnss
function? How can I adjust my code to ensure compatibility with the older version?
Additional Details:
- MATLAB R2024: Works fine
- MATLAB R2022: Fails with the error above
- OS: macOS