Hi,

Right now we're using the following code to compute the Ros time for a message:

def __init__(self):
        self.__ros_base_time = self.get_clock().now()
        self.__dai_base_time = Clock.now()

def ros_time_msg(self, frame: ImgFrame) -> Time:
        dai_time = frame.getTimestamp()
        elapsed = dai_time - self.__dai_base_time
        elapsed = elapsed.total_seconds()
        ros_time = self.__ros_base_time + Duration(seconds=elapsed)
        return ros_time.to_msg()

Our application requires monotonicity, but we're unsure if the code above guarantees that. In the docs I see that there's getTimeStamp(.) and getTimeStampDevice(.)

    getTimestamp(\*args, \*\*kwargs)

    1\. getTimestamp(self: depthai.ImgFrame) -> datetime.timedelta

    Retrieves timestamp related to dai::Clock::now()

    2\. getTimestamp(self: depthai.ImgFrame, offset: depthai.CameraExposureOffset) -> datetime.timedelta

    Retrieves image timestamp (at the specified offset of exposure) related to dai::Clock::now()


    getTimestampDevice(\*args, \*\*kwargs)

    1\. getTimestampDevice(self: depthai.ImgFrame) -> datetime.timedelta        

    Retrieves timestamp directly captured from device's monotonic clock, not synchronized to host time. Used mostly for debugging

    2\. getTimestampDevice(self: depthai.ImgFrame, offset: depthai.CameraExposureOffset) -> datetime.timedelta

    Retrieves image timestamp (at the specified offset of exposure) directly captured from device's monotonic clock, not synchronized to host time. Used when monotonicity is required.

Do we need getTimestampDevice(self: depthai.ImgFrame, offset: depthai.CameraExposureOffset) for guaranteed monotonicity? And if so, how do we use it? There's no example in the docs how to use this function.

Thanks in advance

Hi @WouterOddBot
getTimestamp is just getTimestampDevice + offset (offset from the host's clock). You can use it as such:

# Python, same API for C++ as well
msg: dai.ImgFrame
ts_end_of_exposure = msg.getTimestampDevice()
ts_start_of_exposure = msg.getTimestampDevice(dai.CameraExposureOffset.START)

By default it will be end of exposure (start of MIPI readout, docs here):

std::chrono::time_point<std::chrono::steady_clock, std::chrono::steady_clock::duration> ImgFrame::getTimestamp(CameraExposureOffset offset) const {
    auto ts = getTimestamp();
    auto expTime = getExposureTime();
    switch(offset) {
        case CameraExposureOffset::START:
            return ts - expTime;
        case CameraExposureOffset::MIDDLE:
            return ts - expTime / 2;
        case CameraExposureOffset::END:
        default:
            return ts;
    }
}

    erik Thanks for your explanation. Our initial plan was to do this:

    def __init__(self):
    self.__ros_base_time = self.get_clock().now()
    self.__dai_monotonic_base_time = ? # How to get monotonic base time?

    def ros_time_msg(self, frame: ImgFrame) -> Time:
    dai_time = frame.getTimestampDevice() # get monotonic time
    elapsed = dai_time - self.__dai_monotonic_base_time
    elapsed = elapsed.total_seconds()
    ros_time = self.__ros_base_time + Duration(seconds=elapsed)
    return ros_time.to_msg()

    But I don't know how to get the monotonic base time. We need monotonic time, because the normal depthai clock seems affected by teams leaps.

    erik Hi Erik, well I'm not entirely sure, but it's a guess. Let me start from the beginning. Our robot may operate in places with poor internet connectivity. It may happen that the internet connection drops for quite a while. When there's no internet, the computers in the robot can't sync with the NTP time servers. But when internet comes back, the computers start syncing again, and via the computers also the depthai camera (https://discuss.luxonis.com/blog/3270-host-clock-syncing-improved). That seems to give a small but disruptive time leap in the timestamps.

    So we rather have monotonic timestamps from the camera, since monotonic timestamps are not affected by NTP syncing time leaps. If I understand your documentation correctly, getTimestamp() returns real time timestamp (synced with NTP), whereas getTimestampDevice() returns a monotonic timestamp. Is that correct?

    I hope this clarifies it a bit? Let me know if it's still unclear.

    Hi @WouterOddBot,
    dai.Clock.now() is not related to internet (real) clock, but time since the last computer boot.
    I hope this helps