How to fit an equation (catenary equation in 2D) to a 3D dataset (experimental data of a catenary curve in 3D) ?
20 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
I have an experimental data (3D data) of a catenary curve (basically a rope with 2 attached ends and hanging freely, data got from markers on them).
I want to fit this data with a catenary equation y = a*cosh(x/a).
a is parameterized by an equation stating the length of the physical cable, (length/2) - a* sinh(x/a) = 0
I tried using curve fitting tool and it is asking me an equation in terms of x,y and z. If I give such an equation then it is a surface.
Further, I don't know how to give an equation to parameterize parameter a in the curve fitting tool.
My ultimate requirement is, I want to fit a line (2D equation) in 3D space.
Can anyone please let me know the right tool for this ?
0 commentaires
Réponses (4)
Matt J
le 20 Juil 2023
Modifié(e) : Matt J
le 20 Juil 2023
In the Examples tab of this FEX page,
there is a section Fitting a 2D shape to 3D Points. In particular these lines of code coould easily be adapted to your problem,
pFit=planarFit(XYZ0);%Preliminary plane fit
xy0=pFit.project2D(XYZ0); %Map measured 3D samples to 2D
eFit=ellipticalFit(xy0); %Perform ellipse fit in 2D
XYZ=pFit.unproject3D( cell2mat(eFit.sample(1:360)) ); %Post-sample the ellipse fit and map back to 3D
except that instead of the ellipse fit, you would fit with your own model.
6 commentaires
Matt J
le 28 Juil 2023
scatter3 is used to plot the data points and this is then overlaid with a plot of the fittedplane using fimplicit3.
Mathieu NOE
le 20 Juil 2023
This is a lazy (tired) guy answer
i figure out I could easily transform the 3D array into 2D then do a parabola fit (yes I know it's only an approximation for the catenary cosh model)
load('export_dataset1.mat')
x = cat1_2_x';
y = cat1_2_y';
z = cat1_2_z';
m = numel(x);
figure(1),
plot3(x,y,z,'*-');
xlabel('X')
ylabel('Y')
zlabel('Z')
P = [x y z]; % create array of x,y,z coordinates
V = diff(P,1); % array of vectors
d = sqrt(sum(V.^2,2)); % array of vectors length
% check distance between first and last point (debug)
dmax = P(m,:)-P(1,:);
dmax3D = sqrt(sum(dmax.^2))
% compute raltive angle between successive vectors
ang(1) = 0;
for k = 1:m-2
ang(k+1) = acos(dot(V(k,:)/norm(V(k,:)),V(k+1,:)/norm(V(k+1,:))));
end
angc = cumsum(ang);
angc = angc - angc(end)/2; % so the 2plot shows a balanced (symetrical) start and end angles
% create the 2D points by adding vector coordinates
x(1)= 0;
y(1) = 0;
for k = 1:m-1
x(k+1) = x(k)+d(k)*cos(angc(k));
y(k+1) = y(k)+d(k)*sin(angc(k));
end
% check distance between first and last point (debug)
P = [x y];
dmax = P(m,:)-P(1,:);
dmax2D = sqrt(sum(dmax.^2))
% this is the same as the original data
% now you can fit your 2D data
% as I am lazy and it's getting late here I am doing a parabola fit (and
% not a true cosh model fit
%Set up the appropriate matrix A to find the best-fit parabola of the form y=C+Dx+Ex^2. The
%first column of A will contain all 1's, using the ones() command. The second column of A
%contains x values that are stored in X. The third column of A contains the squared x values
%that are stored in X. Elementwise multiplication of X by itself, using .* operator, will
%produce the desired values for the third column.
A = [ones(m,1) x x.*x];
A_transposeA = A.' * A;
A_transposeY = A.' * y;
%backslash operation to solve the overdetermined system.
Soln2 = A_transposeA\A_transposeY;
%x values to use for plotting the best-fit parabola.
xfit = linspace(min(x),max(x),100);
yfit = Soln2(1) + Soln2(2)*xfit + Soln2(3)*xfit.^2; %
figure(2),
plot(xfit, yfit, x, y, 'r*','Markersize',15);
legend('fit','data');
xlabel('X')
ylabel('Y')
3 commentaires
Mathieu NOE
le 20 Juil 2023
well
that was much faster than I thougt
second catenary results
load('export_dataset2.mat')
x0 = cat6_1_x';
y0 = cat6_1_y';
z0 = cat6_1_z';
figure(1),
plot3(x0,y0,z0,'*-');
xlabel('X')
ylabel('Y')
zlabel('Z')
hold on
% isolate one catenary data (the one which is parrallel to the Y
% direction)
n= find(y0>-0.5 & y0<-0.4);
x = x0(n);
y = y0(n);
z = z0(n);
% sort / unique in x ascending order
[x,ind,~] = unique(x);
y = y(ind);
z = z(ind);
m = numel(x);
plot3(x,y,z,'*r','Markersize',15);
xlabel('X')
ylabel('Y')
zlabel('Z')
hold off
P = [x y z]; % create array of x,y,z coordinates
V = diff(P,1); % array of vectors
d = sqrt(sum(V.^2,2)); % array of vectors length
% check distance between first and last point (debug)
dmax = P(m,:)-P(1,:);
dmax3D = sqrt(sum(dmax.^2))
% compute raltive angle between successive vectors
ang(1) = 0;
for k = 1:m-2
ang(k+1) = acos(dot(V(k,:)/norm(V(k,:)),V(k+1,:)/norm(V(k+1,:))));
end
angc = cumsum(ang);
angc = angc - angc(end)/2; % so the 2plot shows a balanced (symetrical) start and end angles
% create the 2D points by adding vector coordinates
x(1)= 0;
y(1) = 0;
for k = 1:m-1
x(k+1) = x(k)+d(k)*cos(angc(k));
y(k+1) = y(k)+d(k)*sin(angc(k));
end
% check distance between first and last point (debug)
P = [x y];
dmax = P(m,:)-P(1,:);
dmax2D = sqrt(sum(dmax.^2))
% this is the same as the original data
% now you can fit your 2D data
% as I am lazy and it's getting late here I am doing a parabola fit (and
% not a true cosh model fit
%Set up the appropriate matrix A to find the best-fit parabola of the form y=C+Dx+Ex^2. The
%first column of A will contain all 1's, using the ones() command. The second column of A
%contains x values that are stored in X. The third column of A contains the squared x values
%that are stored in X. Elementwise multiplication of X by itself, using .* operator, will
%produce the desired values for the third column.
A = [ones(m,1) x x.*x];
A_transposeA = A.' * A;
A_transposeY = A.' * y;
%backslash operation to solve the overdetermined system.
Soln2 = A_transposeA\A_transposeY;
%x values to use for plotting the best-fit parabola.
xfit = linspace(min(x),max(x),100);
yfit = Soln2(1) + Soln2(2)*xfit + Soln2(3)*xfit.^2; %
figure(2),
plot(xfit, yfit, x, y, 'r*','Markersize',15);
legend('fit','data');
xlabel('X')
ylabel('Y')
John D'Errico
le 20 Juil 2023
Modifié(e) : John D'Errico
le 20 Juil 2023
- How is this a 3-d probem? The curve will lie in a plane. So it is just a 2-d problem. That you have measurements in x,y,z is irrelevant. So reduce it to TWO dimensions first, along the line in the (x,y) plane between the two endpoints.
- Then fit the curve, as a function of the new variable along that line between the endpoints. WTP?
- Finally, Since you have the equation of the line between the endpoints, convert it back into 3-d, if that is what you really wanted.
3 commentaires
Mathieu NOE
le 20 Juil 2023
it would be more efficient to share the data
has you tried to find (fit) the plane to which the data belong ?
VIGNESH BALAJI
le 20 Juil 2023
Modifié(e) : VIGNESH BALAJI
le 20 Juil 2023
4 commentaires
Mathieu NOE
le 21 Juil 2023
well , I don't know howyu could make all this "automatic"
myself I had to do a few manual operations especially for the two catenary data set , to extract each one
then today I have no time for the 3D "backwards" projection topic (sorry)
Voir également
Catégories
En savoir plus sur Delaunay Triangulation dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!