Convert string with cosine/sine or other operations to number

2 vues (au cours des 30 derniers jours)
Gregory Eberle
Gregory Eberle le 9 Nov 2020
I am reading multiple rows of strings from a text file and storing it in a cell. An example of a cell row is shown below:
A = 'X[COS[0.0000] * [-6.2518 + #629] - SIN[0.0000] * [-0.0375] + [0.0290]] Y[-1.8209 + #627] Z[SIN[0.0000] * [-6.2518 + #629] + COS[0.0000] * [-0.0375] + [0.4347]] B[-90.0000] C[0.0000]'
My goal is to evaluate each XYZBC coordinates from string to a double format as shown below:
A = [-6.2228, -1.8209, 0.3972, -90, 0, 8000]
In the case of the X-coordinate, I use the regexprep command to replace the characters into a format Matlab recognises and use the eval command to evaluate the equation as shown exemplary below.
X_coord_new = regexprep(X_coord_old, {'X', '#629', '[', ']', 'COS', 'SIN'},...
{'', '0', '(', ')','cosd','sind'});
X_coord_final = eval(X_coord_new);
I cannot use the str2double command since there is infact math involved to solve the equation, e.g. cosine and sine as well as multiplication/addition/etc.
The problem is that the eval command, and infact the str2num command which also uses the eval command are very slow. Does anybody have any hints or tips of how I can evaluate my strings in a computationally efficient manner? Thank-you!
  4 commentaires
Gregory Eberle
Gregory Eberle le 12 Nov 2020
@Walter Roberson
I am not familier with the link you sent. The presented .m file is not in Matlab synthax. I am actually trying to convert machine GCode coordinates into absolute coordinates.
@ Stephen Cobeldick
The EvalEquation.m works as desired by is unfortunately even slower than the eval or str2num commands from Matlab.
tic; eval( 'cosd(45)+1+2/(2*3)'); toc;
Elapsed time is 0.000526 seconds.
tic; str2num( 'cosd(45)+1+2/(2*3)'); toc;
Elapsed time is 0.012254 seconds.
tic; EvalEquation( 'cosd(45)+1+2/(2*3)'); toc;
Elapsed time is 0.029066 seconds.
I guess I will just have to stick with the eval/str2num commands from Matlab and make an effort not to use it them when not necessary.
Walter Roberson
Walter Roberson le 12 Nov 2020
I looked at gcode a couple of years ago to answer some questions. It did not have the structure you show: the coordinates had to be explicit.
https://www.mathworks.com/matlabcentral/answers/460610-extracting-numbers-from-a-g-code-file

Connectez-vous pour commenter.

Réponses (2)

Mathieu NOE
Mathieu NOE le 9 Nov 2020
hello
so this is my "low level" retrieve function ; remains to do a loop on multiple lines
indexX = strfind(A,'X[');
indexY = strfind(A,'Y[');
indexZ = strfind(A,'Z[');
indexB = strfind(A,'B[');
indexC = strfind(A,'C[');
% 1st value to retrieve /%
stringX = A(indexX:indexY-1);
index1 = strfind(stringX,'[');
index2 = strfind(stringX,'+ #');
valueX = str2num(stringX(index1(3)+1:index2(1)-1));
% 2nd value to retrieve /%
stringY = A(indexY:indexZ-1);
index1 = strfind(stringY,'[');
index2 = strfind(stringY,'+ #');
valueY = str2num(stringY(index1(1)+1:index2(1)-1));
% 3rd value to retrieve /%
stringZ = A(indexZ:indexB-1);
index1 = strfind(stringZ,'[');
index2 = strfind(stringZ,'+ #');
valueZ = str2num(stringZ(index1(3)+1:index2(1)-1));
% 4th value to retrieve /%
stringB = A(indexB:indexC-1);
index1 = strfind(stringB,'[');
index2 = strfind(stringB,']');
valueB = str2num(stringB(index1(1)+1:index2(1)-1));
% 5th value to retrieve /%
stringC = A(indexC:end);
index1 = strfind(stringC,'[');
index2 = strfind(stringC,']');
valueC = str2num(stringC(index1(1)+1:index2(1)-1));
data = [valueX, valueY, valueZ, valueB, valueC];
  10 commentaires
Mathieu NOE
Mathieu NOE le 12 Nov 2020
ok
so if i'm right , for example X is computed like this
cos(0.0000) * (-6.2518) - SIN(0.0000) * (-0.0375) + (0.0290)
that's the -6.2228 output
I assume the " + #629 " does not go into the calculation and must be discarded
same for Y and Z
B and C , no equation , just read the value next to the character
Gregory Eberle
Gregory Eberle le 12 Nov 2020
Correct!
As a note, the angular units are in degrees so Matlab needs to have cosd/sind instead of cos/sin.

Connectez-vous pour commenter.


Mathieu NOE
Mathieu NOE le 12 Nov 2020
so , hopefully now the final code ! had to fight a bit with regexp as I am not super fluent with this coding.
also I remembered that your initial request was to have as output :
A = [-6.2228, -1.8209, 0.3972, -90, 0, 8000]
the '8000' is not in your data file, so I assumed this could be the number of lines scanned. So I added the loop index as the 6th column in the output matrix A = [X Y Z B C k];
the 1000 lines txt scan and processing took : Elapsed time is 0.246920 seconds.
str = fileread('Document1000.txt'); %read entire file into string
parts = strtrim(regexp( str, '(\r|\n)+', 'split')); %split by each line
columns = strtrim( regexp(parts{1}, '\s+', 'split')); %columns
ncol = length(columns); %number of columns
nrows = length(parts); %number of rows
% preallocation
A = zeros(nrows,6);
for k=1:nrows,
data = strtrim(regexp( parts{k}, '\s+', 'split')); %split by spaces
dd = regexp(data,'-?[0-9]+.[0-9]+', 'match'); % extract numeric parts inside the cell
% https://stackoverflow.com/questions/15814592/how-do-i-include-negative-decimal-numbers-in-this-regular-expression
str_temp = strjoin( cat(2,dd{:}), ',') ; % Transform a cell array of cell arrays into string / delimiter = blank or comma
data2 = str2num(str_temp); % convert string to num
% we got : data2 = 0 -6.2518 629 0 -0.0375 0.0290 -1.8209 627 0 -6.2518 629 0 -0.0375 0.4347 -90 0
X = cosd(data2(1))*data2(2) - sind(data2(4))*(data2(5)) + data2(6); % X = cos(0.0000) * (-6.2518) - SIN(0.0000) * (-0.0375) + (0.0290) :
Y = data2(7); % Y[-1.8209 + #627]
Z = sind(data2(9))*data2(10) + cosd(data2(12))*(data2(13)) + data2(14); % Z = [SIN[0.0000] * [-6.2518 + #629] + COS[0.0000] * [-0.0375] + [0.4347]]
B = data2(15);
C = data2(16);
A(k,:) = [X Y Z B C k];
end

Catégories

En savoir plus sur Data Type Identification dans Help Center et File Exchange

Produits


Version

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by