Asked by Rupert Schaffarz
on 17 May 2019

Hello

I have a pointcloud from which I want to extract the border of a street. I have manually created sampling datapoints using the datacursor.

Now I have a list of x, y, z points from which I want to derive a curve (road boarder).

What is the best method of making such a curve given a list of x y z points. It should be smooth.

Thanks for any help!

Answer by Are Mjaavatten
on 20 May 2019

Accepted Answer

Assuming that the points are listed in sequence along your curve, you can express x, y, and z as functions of the (approximate) position along the curve, using splines. To illustrate and test, I first generate a set of points to represent your point cloud. The points are randomly distributed along a 3D curve:

t = sort(rand(50,1))*10;

x = sin(t);

y = cos(1.7*t);

z = sin(t*0.22);

plot3(x,y,z,'*')

grid on

Of course, you do not know the parameter t, so we must create a parameter vector s, based on the euclidean distance between points:

s = zeros(size(x));

for i = 2:length(x)

s(i) = s(i-1) + sqrt((x(i)-x(i-1))^2+(y(i)-y(i-1))^2+(z(i)-z(i-1))^2);

end

Now you have x, y, and z as functions of s, and you can generate splines passing through the points:

ss = linspace(0,s(end),100);

xx = spline(s,x,ss);

yy = spline(s,y,ss);

zz = spline(s,z,ss);

hold on

plot3(xx,yy,zz)

hold off

If there is noise in your data and you want to smooth the curve, consider using polyfit / polyval instead of spline.

If your points are not in sequence, the problem gets MUCH harder to automate, and I recommend that you sequence them manually.

Rupert Schaffarz
on 20 May 2019

Dear Are!

Here is my .mat file.

I have three lines (picked points (x,y,z) with DataCursor from my point cloud):

left_border_subset_sorted

midpointlist

right_border_sorted

They are the left, middle lane and right borders of the road respectively.

The middle lane was calculated manually with the following code.

for i = 1:length(right_border_sorted)

distlist(i) = pdist2(left_border_subset_sorted(i), right_border_sorted(i));

midpointlist(i,:) = (left_border_subset_sorted(i,:) + right_border_sorted(i,:))/2;

end

Calculating the middle lane is probably not correct. So its an estimate.

From this imperfect method plus the imperfections from the picked points I have noise in the z direction (elevation). I would like the resulting curves to be smooth with respect to z and y.

I hope I explained this well.

Thank you so much for your effort and time!

Are Mjaavatten
on 20 May 2019

This will work relativey well with your data:

rb = load('road_boarders');

% Right border:

x = rb.right_border_sorted(:,1);

y = rb.right_border_sorted(:,2);

z = rb.right_border_sorted(:,3);

s = zeros(size(x));

for i = 2:length(x)

s(i) = s(i-1) + sqrt((x(i)-x(i-1))^2+(y(i)-y(i-1))^2+(z(i)-z(i-1))^2);

end

px = polyfit(s,x,3);

py = polyfit(s,y,2);

pz = polyfit(s,z,2);

ss = linspace(0,s(end),100);

% Inspect fit:

figure(1);

subplot(3,1,1);plot(s,x,ss,polyval(px,ss));

subplot(3,1,2);plot(s,y,ss,polyval(py,ss));

subplot(3,1,3);plot(s,z,ss,polyval(pz,ss));

figure(2)

plot3(x,y,z,'.r',polyval(px,ss),polyval(py,ss),polyval(pz,ss),'b')

grid on

% Left border:

x = rb.left_border_subset_sorted(:,1);

y = rb.left_border_subset_sorted(:,2);

z = rb.left_border_subset_sorted(:,3);

s = zeros(size(x));

for i = 2:length(x)

s(i) = s(i-1) + sqrt((x(i)-x(i-1))^2+(y(i)-y(i-1))^2+(z(i)-z(i-1))^2);

end

px = polyfit(s,x,3);

py = polyfit(s,y,2);

pz = polyfit(s,z,2);

ss = linspace(0,s(end),100);

figure(3);

subplot(3,1,1);plot(s,x,ss,polyval(px,ss));

subplot(3,1,2);plot(s,y,ss,polyval(py,ss));

subplot(3,1,3);plot(s,z,ss,polyval(pz,ss));

% Both borders in the same plot:

figure(2);

hold on

plot3(x,y,z,'.r',polyval(px,ss),polyval(py,ss),polyval(pz,ss),'b')

axis equal

If the road has more curves, you could try with higher-order polynomials. However, this approach is not likely to handle more than one or two turns. The curve fitting and spline toolboxes have functions for generating smoothed splines, which could probably do the job. I cannot test this, as I do not have access to those toolboxes.

Rupert Schaffarz
on 20 May 2019

Dear Are!

Thank you so much. It works perfectly.

Again.. I am very grateful for your help!

Cheers

Rupert

Sign in to comment.

Answer by jigsaw
on 21 Sep 2019

Are Mjaavatten's answer works great for me. The following lines can be modified a bit to be more concise. Replace the

s = zeros(size(x));

for i = 2:length(x)

s(i) = s(i-1) + sqrt((x(i)-x(i-1))^2+(y(i)-y(i-1))^2+(z(i)-z(i-1))^2);

end

with

s = [0;cumsum(flip(sqrt((x(end:-1:2)-x(end-1:-1:1)).^2+(y(end:-1:2)-y(end-1:-1:1)).^2+(z(end:-1:2)-z(end-1:-1:1)).^2)))];

Answer by deb.P
on 8 Nov 2019

Are Mjaavatten
on 9 Nov 2019

If you have used the polyfit version, px, py and pz give the coefficients for the fitted polynomials in s. See the docmentation for polyfit for details.

If you used spline, the expressions are piecewise cubic spline polynomials. Se the documentation for spline for details.

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.