Using datenum to calculate acceleration

6 visualizzazioni (ultimi 30 giorni)
Shane Thirkell
Shane Thirkell il 25 Mag 2021
Modificato: Star Strider il 25 Mag 2021
Good Morning all,
I have a CSV-based data set that is created at approximately 1Hz - but not always perfect, and I think I'd like to maintain that precision, as it is a highly accurate satellite clock. In any event, the CSV has many columns, but I only have a few of interest, namely velocity. I've used readtable to obtain the columns, and with an for-loop, would like to calculate the change in velocity (Vdiff) between each sensor output. Currently, I'm converting a datetime to datenum array, subtracting the two (D), and using the seconds(D) function to convert to the exact time elapsed between data points. Eventually I'd like to run this over hundreds of days of data, totalling multiple millions of data points - is there a better way to compute seconds for each calculation? Using datetime directly outputs a "duration" type variable, which I can't use to divide into Vdiff.

Risposte (2)

Star Strider
Star Strider il 25 Mag 2021
I’m not certain that I understand in detail what you’re doing.
Using datenum is likely the best option here. I experimented with caldiff (using synthetic data) and was not able to get a satisfactory result of the sort you probably need, although with your data it may work.
The diff function has the disadvantage of shortening the output by one element, since it takes successive differences. One alternative is to compute the numeric derivative with the gradient function, and to get the acceleration from the velocity and time vectors, use them together as:
dVdt = gradient(velocity) ./ gradient(time);
The calculation you choose entirely depends on the result you want.
  2 Commenti
Shane Thirkell
Shane Thirkell il 25 Mag 2021
Modificato: Shane Thirkell il 25 Mag 2021
Thanks, this is a helpful perspective. I think I'm able to use the datenum output directly by multiplying by 24*3600 - effectively giving me the exact duration in seconds as a "double". I'll give the gradient() function a try, but when I start to move towards running this calculation on 10 million+ data points I have a feeling I might run into issues. For now: Acc(i) = (V(i)-V(i-1))/(24*3600*(datenum(t(i))-datenum(t(i-1))). This way, for example, I actually am able to capture the fact that the "dt" is actually 1.005 seconds in duration, rather than directly from datetime->duration which outputs 00:00:01....slightly less accurate, I would think.
Seems to run relatively quickly, but I've yet to run this on more than one day of data (~86400 data points)
Thanks!
Star Strider
Star Strider il 25 Mag 2021
Modificato: Star Strider il 25 Mag 2021
My pleasure!
The datenum function outputs in days and decimal fractions of days (out to whatever tthe precision is, for example milliseconds), so it is likely not necessary to perform the conversion to seconds (and decimal fractions of them) except at the end of the calculation. I believe that datetime variables can go to microseconds at least, although that obviously depends on the resolution of the time measurement itself.
I’m not certain that there is one ‘correct’ way to do this, however converting back to datetime to store summary data may offer some advantages, although for calculations of the sort you’re doing, it’s not going to be efficient, even it there turns out to be a way to do it (that I haven’t discovered yet).
EDIT — (25 May 2021 at 16:26)
In the interim, I figured out how to do that only using datetime variables and functions —
DT = datetime('now')+seconds(sort(rand(2000,1)*100000)) % Create datetime’ Array
DT = 2000×1 datetime array
25-May-2021 16:25:47 25-May-2021 16:25:47 25-May-2021 16:25:53 25-May-2021 16:26:58 25-May-2021 16:27:05 25-May-2021 16:27:16 25-May-2021 16:27:17 25-May-2021 16:27:19 25-May-2021 16:27:23 25-May-2021 16:28:21 25-May-2021 16:30:49 25-May-2021 16:33:03 25-May-2021 16:34:34 25-May-2021 16:35:42 25-May-2021 16:35:51 25-May-2021 16:35:59 25-May-2021 16:37:51 25-May-2021 16:40:07 25-May-2021 16:40:09 25-May-2021 16:42:31 25-May-2021 16:43:34 25-May-2021 16:44:37 25-May-2021 16:45:23 25-May-2021 16:45:44 25-May-2021 16:46:13 25-May-2021 16:46:37 25-May-2021 16:46:44 25-May-2021 16:48:25 25-May-2021 16:48:40 25-May-2021 16:53:42
dDT = caldiff(DT,'time') % Calculate Differences
dDT = 1999×1 calendarDuration array
0h 0m 0.24357s 0h 0m 5.6315s 0h 1m 5.4449s 0h 0m 7.0419s 0h 0m 10.446s 0h 0m 1.1956s 0h 0m 1.7729s 0h 0m 4.4009s 0h 0m 57.778s 0h 2m 28.029s 0h 2m 13.922s 0h 1m 31.359s 0h 1m 7.53s 0h 0m 9.4874s 0h 0m 8.0609s 0h 1m 51.701s 0h 2m 16.171s 0h 0m 1.6133s 0h 2m 22.608s 0h 1m 2.1867s 0h 1m 3.7545s 0h 0m 45.499s 0h 0m 21.05s 0h 0m 29.214s 0h 0m 23.586s 0h 0m 7.3832s 0h 1m 40.745s 0h 0m 15.329s 0h 5m 2.1456s 0h 0m 35.46s
tsDT = seconds(time(dDT)) % Get Seconds
tsDT = 1999×1
0.2436 5.6315 65.4449 7.0419 10.4459 1.1956 1.7729 4.4009 57.7783 148.0294
It also calculates the second differences correctly so that it doesn’t start over with a new day (after midnight). The differences are correct.
.

Accedi per commentare.


Steven Lord
Steven Lord il 25 Mag 2021
Using datetime directly outputs a "duration" type variable, which I can't use to divide into Vdiff.
That's true, but you don't need to convert to a datenum.
format longg
dt1 = datetime('now')
dt1 = datetime
25-May-2021 15:17:15
P = 5*rand
P =
4.70701522436636
dt2 = dt1 + seconds(P)
dt2 = datetime
25-May-2021 15:17:19
difference = dt2 - dt1
difference = duration
00:00:04
differenceInSeconds = seconds(difference)
differenceInSeconds =
4.70701522436636
check = differenceInSeconds - P
check =
0
differenceInSeconds matches P. Of course this example is "synthetic" in that I knew P ahead of time and used it to create dt2. But if you started with dt1 and dt2 you could find P aka differenceInSeconds and you can divide by differenceInSeconds.
  2 Commenti
Shane Thirkell
Shane Thirkell il 25 Mag 2021
Thanks, I agree with your result. Though, as stated before, would using an exterior function like "seconds()" introduce a much slower code than doing the arithmetic directly? It appears that it does run much faster in the loop by converting datenum into seconds rather than using the seconds function.
Steven Lord
Steven Lord il 25 Mag 2021
Do you need a loop or can you operate on the vectors of data at once?
x = randi([-10 10], 10, 1)
x = 10×1
2 -10 -6 -9 -10 -2 -6 -9 -3 6
dt = datetime('now') + seconds(x)
dt = 10×1 datetime array
25-May-2021 16:12:20 25-May-2021 16:12:08 25-May-2021 16:12:12 25-May-2021 16:12:09 25-May-2021 16:12:08 25-May-2021 16:12:16 25-May-2021 16:12:12 25-May-2021 16:12:09 25-May-2021 16:12:15 25-May-2021 16:12:24
seconds(diff(dt))
ans = 9×1
-12 4 -3 -1 8 -4 -3 6 9
diff(x)
ans = 9×1
-12 4 -3 -1 8 -4 -3 6 9

Accedi per commentare.

Categorie

Scopri di più su Dates and Time in Help Center e File Exchange

Tag

Prodotti

Community Treasure Hunt

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

Start Hunting!

Translated by