Skip to content

Global Camera Time - #3909

Merged
ev-mp merged 21 commits into
realsenseai:developmentfrom
doronhi:hwsystime
May 16, 2019
Merged

Global Camera Time#3909
ev-mp merged 21 commits into
realsenseai:developmentfrom
doronhi:hwsystime

Conversation

@doronhi

@doronhi doronhi commented May 5, 2019

Copy link
Copy Markdown
Contributor

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

dorodnic and others added 13 commits May 5, 2019 14:51
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.
@dorodnic
dorodnic changed the base branch from master to development May 5, 2019 18:58
@dorodnic dorodnic changed the title Hwsystime Global Camera Time May 5, 2019

@bfulkers-i bfulkers-i left a comment

Copy link
Copy Markdown
Contributor

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.

Comment thread 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;

Copy link
Copy Markdown
Contributor

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>

Copy link
Copy Markdown
Contributor Author

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.

Copy link
Copy Markdown
Contributor

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.

Copy link
Copy Markdown
Contributor Author

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.

Comment thread src/global_timestamp_reader.cpp Outdated
bool time_diff_keeper::update_diff_time()
{
using namespace std::chrono;
const static double diffThresh = 500;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused?

Copy link
Copy Markdown
Contributor Author

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();

Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Contributor Author

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.

Comment thread include/librealsense2/h/rs_frame.h Outdated
*/
rs2_time_t rs2_get_frame_timestamp(const rs2_frame* frame, rs2_error** error);

/**

Copy link
Copy Markdown
Contributor

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];

Copy link
Copy Markdown
Contributor

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

@dorodnic dorodnic mentioned this pull request May 8, 2019

@ev-mp ev-mp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good

@ev-mp
ev-mp merged commit 1fd3144 into realsenseai:development May 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants