Recorder Data: SampleCounter vs. Clock Time

[RMP 10.4.3]

I’m trying to synchronize data obtained from recorders (captured every sample) and data that is time serialized with a high resolution time stamp (μs precision).

I’m trying to merge the recorder data with the other data. My observation is that I cannot precisely place the recorder data among records with higher-precision timestamps.

I think my basic question is, if I compared the sample counter to a simple, infinite resolution clock, would adjacent sample counter values be approximately 1/sample_rate seconds apart? Of course, the answer is “yes,” depending on how approximate I wanted.

Perhaps a better phrasing of the question is:

How precisely spaced are successive recorder samples (whose sample counter values differ by 1)?

Consider this “timing diagram.”

The t values at the top are real time values (expressed in μs precision). The s values are sample counts. The green and red are possible realities of where, in real time, the sample counter value was recorded (or the recorder data was measured).

How precisely spaced are the sample count values in the recorder data?

Of what practical value is the answer to this question?

Suppose I want to calculate acceleration based on velocity (or worse, position). I have to assume something about time based on the sample count. Based on the precision of the spacing, I may need to accommodate the inaccuracy of my time assumptions, especially if I intend to compare two calculated values.

Is there a good way to synchronize sample counter with high(er) resolution time stamps?

This is a general strategy question that you guys may have already solved. I haven’t yet thought of a good way to synchronize timestamps and sample counter values. Do you ever need to do this?

On a perfect CPU (no jitter or latency) and the RMP waking precisely when it’s scheduled (let’s say every millisecond (sample rate = 1000Hz)), it would be just like your green values.

In the real world, there will some measurable jitter and latency for each sample. The good news is that you can read (or record) the number of microseconds elapsed from the previous sample using RSIControllerAddressTypeFIRMWARE_TIMING_DELTA, added in 10.4.3.

If you record that value (it’s a 32-bit integer), you should be able to more accurately calculate your velocity.

The ideal strategy for accurate time stamps is to use a PC which has minimal jitter/latency. We’re about to release an industrial PC where we can run for days at 1000Hz with FIRMWARE_TIMING_DELTA (nominal 1000us) staying with a range of +/- 15us (985us to 1015us). Recording the delta on your system should give you some indication on the necessity of adjusting your calculations.

1 Like

For some additional detail about the last question, I have attempted to record “clock sync” data, where I combine the sample counter (returned from MotionController::SampleCounterGet()) with a high resolution timestamp (obtained in C++ using std::chrono::system_clock::now().time_since_epoch()).

My initial assumption is that if I normalized the sample counts by subtracting the initial sample counter value (s_0) from all of them and did something similar with my μs timestamp data, I would then find a constant value, k_μs that related the timestamps to the sample counts (so that I could at least turn my timestamps into sample counts), like

((t - t_0) + k_us) / 1000 = (s - s_0)

This sounds good on paper, but the results I don’t match the theory.

             s          t      k
326          0      0.000  0.000
663         17     16.829  0.171
1468        45     45.162 -0.162
1813        63     62.694  0.306
2222        78     78.281 -0.281
       ...        ...    ...
1782135  35579  35578.519  0.481
1782472  35591  35590.708  0.292
1782809  35606  35605.780  0.220
1783146  35620  35619.538  0.462
1783483  35634  35633.643  0.357

[3806 rows x 3 columns]

I don’t see any consistency in the calculated values of k. What could account for that?

I have some ideas, but I don’t know how much confidence to place in them.

  • Calculating a C++ timestamp takes a “long time” (e.g. tens or hundreds of μs, perhaps)
  • My retrieval of the sample counter takes a “long time”
  • I’m misterpreting the meaning of SampleCounterGet()
  • The behavior model I’m using is incorrect ((t + k)/1000 = s)
  • The complexity of my app is violating any simplifying assumptions that I’m making.

Are there other likely things that could account for this discrepancy?

That’s cool. I will start including this value with my recorder data.

As a corollary question, do the recorders sample their data at the same time? If I want to record more than 32 pieces of data, I have to use multiple recorders. Can I expect all the data to “come in” on multiple recorders at once, or does it very much depend on when I call RecorderRecordDataRetrieveBulk(...)? Also, should I expect to get the same values for FIRMWARE_TIMING_DELTA on two recorders in the same “batch,” or are they essentially independent of one another and any aligning of timestamps (sample counter) is a coincidence or the result of calling the pertinent API functions all during the same sample (ms)?

I suppose this is what jitter looks like in the firmware timing delta, right?

The RMP sample increments at the beginning of each sample. SampleCounterGet() just reads that value over shared memory (~500ns) so theoretically you could get system_clock::now() timestamps over 999us that all give you the same value for the RMP sample counter.

In our experience a now() timestamp is in the 10s of nanoseconds. time_since_epoch() will add to that.

Yes that looks like two instances of ~100us jitter. I suspect you’d see similar results with the INtime jitter tool.

Out of curiosity, I wrote my own crude test.

I get results similar to yours for ::now().

time_since_epoch generally finishes in <1ns when compiler optimizations (for speed) are enabled.

Similar to my initial question, would the “precise” timestamp between successive changes to that internal datum in memory be equally spaced? Is this, too, merely a function of CPU jitter?

I’m trying to make sense of my (failed) attempt to reconcile timestamps and sample counter values.

If I had to guess, it could be that you’re measuring time on Windows and the RMP timestamps are coming from INtime. Keep in mind that once the network is operational, the RMP firmware is synchronizing to the first node’s clock (distributed clocks feature), which it does by adjusting some low-level INtime system clocks.