How to compute the lap count in the data

I want to compute the lap count of a car, means how many times a car has completed a lap. I have coordinates of the car attached as a csv file and size of the scene is height = 0.33 width = 0.342. I take the starting point as a first row of the csv file attached. The coordinates looks like this
Now I want to compute how many laps the car has taken, my logic to compute the laps is given below, it is that if the car has reached its starting point after crossing the vertical line than make it a one count of lap, now the thing is that this game has different level in the first level car start from one starting point and go in anticlockwise direction and in the next level it has another starting point and it goes in clockwise direction. I am attaching my logic as a function, in this data the lap count should be 11 but my function is giving me the count of 19. What should be done to avoid false lap count.
I call the attached function as :
filename='C:\Users\Windows 10\re.csv'
data = readtable(filename);
starting_y = data.YCoordinate(1);
width = 0.342;
height = 0.33;
lap_count = count_laps(data, width, height, starting_y, 0.001);
disp(['Lap Count: ', num2str(lap_count)]);

2 Comments

Have you figured out what about your data or code has caused it to come up with 19 as the number of laps?
Yes, the logic seems to be not that robust, since a lap is defined as moving over a line along a Y coordinate, often the car crosses that line twice, once going down, and once going up, the line for the lap is defined using the start point, sometimes the car doesn't trigger the lap because it doesn't go down far enough,the car teleports to the other side of the track, with a 14-16 second gap in observations because of level change.

Sign in to comment.

 Accepted Answer

hello
this would be my suggestion :
transform your cartesian data into polar ones and count how many complete revolution your car has done (in both directions)
the plot below is the angle (theta) value obtained after cart2pol conversion , divided by 2pi to have it in turns
then there is a bit of further processing to count only the completed revs (therefore the use of floor) that are plotted as red diamonds
so here we can see you have done 2 , 2 , 2 , 5 laps = 11 laps total
hope it helps
filename='result.csv';
data = readtable(filename);
x = data.XCoordinate;
y = data.YCoordinate;
samples = numel(x);
center_x = mean(x);
center_y = mean(y);
[theta,r] = cart2pol(x-center_x,y-center_y);
theta = theta - theta(1); % when we start , this is our reference (finish) line (so theta must start at zero)
turns = unwrap(theta)/(2*pi); % convert theta in radians into turns
% find the positive and negative peaks (to know when we change direction)
[PKSpos,LOCSpos] = findpeaks(turns,'MinPeakDistance',1000,'MinPeakWidth',1000);
[PKSneg,LOCSneg] = findpeaks(-turns,'MinPeakDistance',1000,'MinPeakWidth',1000);
% round values to nearest integer (only completed turns must be taken into
% account)
PKSpos = floor(PKSpos);
PKSneg = -floor(PKSneg);
% merge locs and pks data and add start / end points
start_p = turns(1);
end_p = turns(samples);
end_p = floor(end_p)*sign(end_p);
LOCS_all = [1;LOCSpos;LOCSneg;samples];
PKS_all = [start_p;PKSpos;PKSneg;end_p];
% sort indexing in ascending order
[LOCS_all,I] = sort(LOCS_all);
PKS_all = PKS_all(I);
turns_completed = sum(abs((diff(PKS_all))));
plot(turns);
hold on
plot(LOCS_all,PKS_all,'dr');
title(['Turns completed = ' num2str(turns_completed)]);
xlabel('Samples');
ylabel('Turns');

14 Comments

MakM
MakM on 18 Apr 2023
Edited: MakM on 18 Apr 2023
HI Mathieu, Thanks for the detailed answer, looks like working in many cases, also it is giving mn an extra no of lap in other cases, like if I have 9 laps, it is giving me value 10, is this due tu any floor operation?
Edit: If I have 32 laps, it gives me 42 but after changing the function values to 1900 it is giving me 34 laps.
[PKSpos,LOCSpos] = findpeaks(turns,'MinPeakDistance',1900,'MinPeakWidth',1900);
[PKSneg,LOCSneg] = findpeaks(-turns,'MinPeakDistance',1900,'MinPeakWidth',1900);
how can we select 'MinPeakDistance' values?
hello
I admit the solution is not perfect as we need to look at the shape of the plot to decide what to use in the MinPeakDistance value . In the example above we see that the maxima are at least 1000 samples apart so that was the idea .
Now the next step would be to have a solution that does not rely on this tweak
can you share the data of your 32 turns case ?
Yes sure, I am attaching the data.
I ran the code without modification
the plot seems to tell me (I can count manually also) that 42 laps were completed
2 + 2 + 2 +14 + 2 + 3 + 13 + 2 + 2
how do you come to 32 ?
I counted the car laps while playing game.
well, I cannot figure out why the difference
could it be that your 32 laps are only the values in bold characters below :
2 + 2 + 2 +14 + 2 + 3 + 13 + 2 + 2
but when we change the peakfunction values, it comes near 32, i.e 34, should we fine tune the peakfunction values?
[PKSpos,LOCSpos] = findpeaks(turns,'MinPeakDistance',1900,'MinPeakWidth',1900);
[PKSneg,LOCSneg] = findpeaks(-turns,'MinPeakDistance',1900,'MinPeakWidth',1900);
like when I used this values, turns become 34, which is more near to 32.
Also I am attaching another gameplay which has 5 laps, the code is calculating correctly (giving 6 laps because of floor) but why the graph is like that.Data and image attached, diamond is at 2 and peak is at 0?
answer to previous comment :
if you increase ,'MinPeakWidth', from 1000 to 1900 you notice that you loose some negative peaks in the count (case result_32.csv)
with MinPeakWidth = 1000
with MinPeakWidth = 1900
for your last comment, I corrected a bug in this line :
end_p = floor(end_p)*sign(end_p);
should be :
end_p = floor(abs(end_p))*sign(end_p);
and now the result and plot is correct ( 5 laps)
NB that for this case I had to reduce MinPeakWidth to 100 as the data length is quite shorter
so here the updated code :
clc
clearvars
% filename='result.csv'; % use 'MinPeakWidth',1000
% filename='result_32.csv'; % use 'MinPeakWidth',1000
filename='result_16.csv'; % use 'MinPeakWidth',100
data = readtable(filename);
x = data.XCoordinate;
y = data.YCoordinate;
samples = numel(x);
center_x = mean(x);
center_y = mean(y);
[theta,r] = cart2pol(x-center_x,y-center_y);
theta = theta - theta(1); % when we start , this is our reference (finish) line (so theta must start at zero)
turns = unwrap(theta)/(2*pi); % convert theta in radians into turns
% find the positive and negative peaks (to know when we change direction)
[PKSpos,LOCSpos] = findpeaks(turns,'MinPeakDistance',1000,'MinPeakWidth',100);
[PKSneg,LOCSneg] = findpeaks(-turns,'MinPeakDistance',1000,'MinPeakWidth',100);
% round values to nearest integer (only completed turns must be taken into
% account)
PKSpos = floor(PKSpos);
PKSneg = -floor(PKSneg);
% merge locs and pks data and add start / end points
start_p = turns(1);
end_p = turns(samples);
end_p = floor(abs(end_p))*sign(end_p);
LOCS_all = [1;LOCSpos;LOCSneg;samples];
PKS_all = [start_p;PKSpos;PKSneg;end_p];
% sort indexing in ascending order
[LOCS_all,I] = sort(LOCS_all);
PKS_all = PKS_all(I);
turns_completed = sum(abs((diff(PKS_all))));
plot(turns);
hold on
plot(LOCS_all,PKS_all,'dr');
title(['Turns completed = ' num2str(turns_completed)]);
xlabel('Samples');
ylabel('Turns');
Thankyou Mathieu, you are life saviour :) From the last comment, as the peak is decreasing, why the diamond is at -1 than?
MakM
MakM on 18 Apr 2023
Edited: MakM on 18 Apr 2023
also, this end_p = floor(abs(end_p))*sign(end_p); is adding one more lap to some cases.
Added this and it is working correctly in many cases.
if sign(end_p)==1 || sign(end_p)==0
end_p = floor(end_p)*sign(end_p);
elseif sign(end_p)==-1
end_p = ceil(end_p)*sign(end_p);
end
ok glad you found the ultimate solution !
and FYI, the last diamond is at -1 and not -2 because the last point at not reached / passed -2 (is above -2)

Sign in to comment.

More Answers (0)

Categories

Find more on Conway's Game of Life in Help Center and File Exchange

Tags

Asked:

on 16 Apr 2023

Commented:

on 18 Apr 2023

Community Treasure Hunt

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

Start Hunting!