Global Camera Time - #3909
Conversation
in realsense_metadata_win10.ps1 fixed D435i pid from 0B18 to 0B3A add timestamp domain: RS2_TIMESTAMP_DOMAIN_HARDWARE_SYSTEM add function to device: get_device_time() ds5-device use global_timestamp_reader above ds5_timestamp_reader_from_metadata rs-data-collect - check file writability before start collecting.
Add std check to avoid adding big time gaps.
…in global_timestamp_reader. l500 uses global_timestamp_reader. l500_timestamp_reader_from_metadata - fix time resolution.
…_DOMAIN_GLOBAL_time re-implement get_device_time()
…ing filter, calculate linear equation between firmware time and system time.
remove loop handling from l500_timestamp_reader_from_metadata::get_frame_timestamp. Handled in global_timestamp_reader. fix TIMESTAMP_USEC_TO_MSEC declaration.
bfulkers-i
left a comment
There was a problem hiding this comment.
The points I'd like to see clarified are:
- What is the expected accuracy?
- How is the latency of the device response / USB taken into account?
- What happens when timestamps wrap?
To see how T265 deals with this same issue, look at https://github.com/IntelRealSense/librealsense/blob/master/third-party/libtm/libtm/src/Device.cpp#L230. The basic idea is to regularly query the device for its current time and measure both the response and the round trip time of the request to account for latency. See https://en.wikipedia.org/wiki/Network_Time_Protocol#Clock_synchronization_algorithm for a relevant figure.
| LOG_DEBUG("time_diff_keeper::update_diff_time - in"); | ||
| std::lock_guard<std::recursive_mutex> lock(_mtx); | ||
| LOG_DEBUG("time_diff_keeper::update_diff_time - lock"); | ||
| double system_time = static_cast<double>(duration_cast<nanoseconds>(system_clock::now().time_since_epoch()).count()) * TIMESTAMP_USEC_TO_MSEC * TIMESTAMP_USEC_TO_MSEC; |
There was a problem hiding this comment.
This should be a std::chrono conversion <double, std::chrono::milliseconds>
There was a problem hiding this comment.
by casting nanoseconds to milliseconds I get better accuracy. Or so it seems.
There was a problem hiding this comment.
My mistake, what you likely want is duration<double, std::milli>, notice the difference between this and std::chrono::milliseconds which is duration</*signed integer type of at least 45 bits*/, std::milli>. In the latter case you get integer milliseconds, which is why you feel you are getting better accuracy by not using that.
There was a problem hiding this comment.
Thanks. Both for the note regarding the round-trip delay and for the system time reading method.
I updated accordingly.
| bool time_diff_keeper::update_diff_time() | ||
| { | ||
| using namespace std::chrono; | ||
| const static double diffThresh = 500; |
There was a problem hiding this comment.
Thank you, indeed unused.
| { | ||
| // A time loop happend: | ||
| LOG_DEBUG("time_diff_keeper::call reset()"); | ||
| _coefs.reset(); |
There was a problem hiding this comment.
What is the expected behavior when the timestamps wrap?
There was a problem hiding this comment.
When timestamp wraps, the time samples for calculating the equation for firmware time to system time are erased. Coefficients a=1, b=0 are used for the next 100 milliseconds, until some samples accumulate again. The assumption is that in that time, the firmware time and system time will not diverge.
| */ | ||
| rs2_time_t rs2_get_frame_timestamp(const rs2_frame* frame, rs2_error** error); | ||
|
|
||
| /** |
There was a problem hiding this comment.
Split and resubmit as a separate PR
| txtTimeStamp.Text = String.Format("{0,-20:0.00}", depthFrame.Timestamp) + "(" + depthFrame.TimestampDomain.ToString() + ")"; | ||
| Dispatcher.Invoke(new Action(() => | ||
| { | ||
| String color_dev_sn = new Sensor.CameraInfos(depthFrame.Sensor)[CameraInfo.SerialNumber]; |
There was a problem hiding this comment.
Rename the var: colordepth_dev_sn
For synchronization of several cameras on the same machine a common timestamp for all streams is needed.
This PR periodically compares the device time and the computer time to calculate a linear equation describing the connection between them. Then it applies the function to every frame in every stream.
As an additional by-product, it handles the 32 bytes issue of time stamp being reset every hour or so.
The function set the timestamp domain to "RS2_TIMESTAMP_DOMAIN_GLOBAL_TIME" as defined in rs_frame.h
If the metadata is not available the global timestamp is not invoked - timestamp domain remains RS2_TIMESTAMP_DOMAIN_SYSTEM_TIME.
The PR requires the implementation of a get_device_time() function to work - currently implemented for D400 series and L500 camera only.
Tracked on: RS-3975