How to fit an equation (catenary equation in 2D) to a 3D dataset (experimental data of a catenary curve in 3D) ?
15 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
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 Commenti
Risposte (4)
Matt J
il 20 Lug 2023
Modificato: Matt J
il 20 Lug 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 Commenti
Matt J
il 28 Lug 2023
scatter3 is used to plot the data points and this is then overlaid with a plot of the fittedplane using fimplicit3.
Mathieu NOE
il 20 Lug 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 Commenti
Mathieu NOE
il 20 Lug 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
il 20 Lug 2023
Modificato: John D'Errico
il 20 Lug 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 Commenti
Mathieu NOE
il 20 Lug 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
il 20 Lug 2023
Modificato: VIGNESH BALAJI
il 20 Lug 2023
4 Commenti
Mathieu NOE
il 21 Lug 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)
Vedere anche
Categorie
Scopri di più su Delaunay Triangulation in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!