-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Global Camera Time #3909
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
src/global_timestamp_reader.cpp
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a std::chrono conversion <double, std::chrono::milliseconds>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
by casting nanoseconds to milliseconds I get better accuracy. Or so it seems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Both for the note regarding the round-trip delay and for the system time reading method.
I updated accordingly.
src/global_timestamp_reader.cpp
Outdated
bool time_diff_keeper::update_diff_time() | ||
{ | ||
using namespace std::chrono; | ||
const static double diffThresh = 500; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, indeed unused.
{ | ||
// A time loop happend: | ||
LOG_DEBUG("time_diff_keeper::call reset()"); | ||
_coefs.reset(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the expected behavior when the timestamps wrap?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
include/librealsense2/h/rs_frame.h
Outdated
@@ -99,6 +99,14 @@ rs2_timestamp_domain rs2_get_frame_timestamp_domain(const rs2_frame* frameset, r | |||
*/ | |||
rs2_time_t rs2_get_frame_timestamp(const rs2_frame* frame, rs2_error** error); | |||
|
|||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename the var: colordepth_dev_sn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good
Do we have more detailed info in the official documentation? |
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