2017-04-13 74 views
2

我有很长的一圈玩具车围绕轨道运行5-6圈的一系列的[x,y]坐标值。每圈数据点的数量不一致(圈数有50-60个[x,y]点之间的任何地方)。 Matlab中绘制的数据是有意义的,它绘制的汽车,因为它移动在赛道:以可变采样率对周期性数据进行平均

plot

不过,我需要以某种方式平均嘈杂圈打造轨道更精确的一张地图。

我试图标记开始的轨道,以确定一个新圈的开始,然后平均每圈的每个对应点,但由于每圈的数据点数量不同导致更多的错误。

我想过整理[x,y]数据将所有点加入一圈,但由于轨道是循环的,所以这不起作用。

有谁知道一种方式来以某种方式平均我的数据合并圈数在一起?

+0

您的轨道是圆形的吗? – Suever

+0

在这种情况下,它实际上是一个圆角矩形,但理想情况下,我想要一个适用于任何轨道形状的解决方案 – enrico

+0

您是否打算制作轨道地图(因为您不知道轨道)或更准确地跟踪汽车的动作(你知道轨道的形状)? – Wolfie

回答

2

做到这一点的一种方法是定义轨道的开始,然后通过路径的归一化弧长参数化循环周围的每个遍历。然后,您可以使用此参数化在沿着轨道的特定间隔内插每条曲线,并对结果进行平均。

% Assume that the first point is the start point (t = 0) 
start_point = path(1,:); 

% Compute the distance to this point for all data points 
distances = sqrt(sum(bsxfun(@minus, path, start_point).^2, 2)); 

% Find the minima of this curve (these are all the times that the car passed the start) 
% We apply some smoothing to get rid of necessary noise. Really depends on your data 
[~, locs] = findpeaks(smooth(-distances, 20)); 

% Make sure we include the first and last point 
locs = [1; locs; numel(distances)]; 

% Desired samples for each loop 
nSamples = 1000; 

% Pre-allocate the outputs 
xpoints = zeros(numel(locs) - 1, nSamples); 
ypoints = zeros(numel(locs) - 1, nSamples); 

for k = 1:(numel(locs) - 1) 
    % Get the coordinates recorded for this particular loop 
    loop_points = path(locs(k):locs(k+1),:); 

    % Compute the cumulative arc-length using these points 
    arc_length = cumsum([0; sum(diff(loop_points, [], 1).^2, 2)]); 

    % Normalize the arc_length between 0 and 1 
    arc_length = arc_length ./ arc_length(end); 

    % Interpolate along the curve 
    xpoints(k,:) = interp1(arc_length, loop_points(:,1), linspace(0, 1, nSamples)); 
    ypoints(k,:) = interp1(arc_length, loop_points(:,2), linspace(0, 1, nSamples)); 
end 

% Average all the x and y locations 
X = mean(xpoints, 1); 
Y = mean(ypoints, 1); 

plot(X, Y) 

我们可以通过一个正圆要测试这一点,一些噪音添加到每个电路和改变样本数量每次

nLoops = 10; 

x = []; 
y = []; 

for k = 1:nLoops 
    nSamples = randi([50, 70]); 

    t = linspace(0, 2*pi, nSamples + 1); 
    t(end) = []; 

    x = cat(1, x(:), cos(t(:)) + 0.1 * (rand(size(t(:))) - 0.5)); 
    y = cat(1, y(:), sin(t(:)) + 0.1 * (rand(size(t(:))) - 0.5)); 
end 

path = [x(:), y(:)]; 

enter image description here

注:findpeakssmooth是可能被MATLAB文件交换中的函数替换的工具箱函数。或者,如果您知道已知道,那么您可以完全取消findpeaks的使用。

+0

这在你的演示中看起来很有效。也许值得一提的是['findpeaks'](https://uk.mathworks.com/help/signal/ref/findpeaks.html?searchHighlight=findpeaks&s_tid=doc_srchtitle)和['smooth'](https://uk.mathworks .com/help/curvefit/smooth.html?searchHighlight = smooth&s_tid = doc_srchtitle)分别使用信号处理和曲线拟合工具箱。 – Wolfie

+0

@Wolfie更新的注意事项 – Suever

+0

@Suever感谢这似乎是一个非常好的解决方案,但是我得到了一些Matlab错误与我的数据。当我进入for循环时,它停止运行,并说“网格向量不是严格单调递增的。”你知道这是什么意思吗? – enrico