简体   繁体   中英

Accelerometer SensorEvent timestamp

Im currently working on a android application.. I have to log the accelerometer sensor event coordinate with event time. I got the sensor event timestamp like "3497855005850" but i am not able to convert event timestamp into user readable date time format.Thanks in advance

How can i convert SensorEvent timestamp to unix timestamp?

The sensor timestamp is actually nanoseconds of uptime, not system time in nanoseconds. See SensorEvent.timestamp to absolute (utc) timestamp? .

In theory, you can convert sensor timestamp to time in milliseconds using:

long timeInMillis = (new Date()).getTime() 
                    + (sensorEvent.timestamp - System.nanoTime()) / 1000000L;

You could even bracket the (new Date()).getTime() call with two System.nanoTime() calls and average them to get closer to the actual offset.

Then you can format the sensor time as date and time.

You can set referent time variables in your onSensorChanged(SensorEvent) function.

Reference for current time and event time. When event arrives subtract sensor referent time from event time and you will have difference in nanoseconds. You can add that difference divided by 1,000,000 to current time reference to get event time in milliseconds.
Error with calculating this can be max 0.5 milliseconds for one event. You can minimize error by changing referent times occasionally.

private long sensorTimeReference = 0l;
private long myTimeReference = 0l;

public void onSensorChanged(SensorEvent event) {
    // set reference times
    if(sensorTimeReference == 0l && myTimeReference == 0l) {
        sensorTimeReference = event.timestamp;
        myTimeReference = System.currentTimeMillis();
    }
    // set event timestamp to current time in milliseconds
    event.timestamp = myTimeReference + 
        Math.round((event.timestamp - sensorTimeReference) / 1000000.0);
    // some code...
}

The official SensorEvent#timestamp documentation states:

[event.time is] The time in nanoseconds at which the event happened. For a given sensor, each new sensor event should be monotonically increasing using the same time base as SystemClock.elapsedRealtimeNanos() .

Challenge

  • Some manufacturers/devices use the SystemClock.currentTimeNanos() instead (eg Nexus 4).

Device-independent solution:

/**
 * Calculates the static offset (ms) which needs to
 *  be added to the `event.time` (ns) to get the Unix
 *  timestamp of the event.
 *
 * @param eventTimeNanos the {@code SensorEvent.time} to be used to determine the time offset
 * @return the offset in milliseconds
 */
private long eventTimeOffset(final long eventTimeNanos) {
    // Capture timestamps of event reporting time
    final long elapsedRealTimeMillis = SystemClock.elapsedRealtime();
    final long upTimeMillis = SystemClock.uptimeMillis();
    final long currentTimeMillis = System.currentTimeMillis();

    // Check which timestamp the event.time is closest to the event.time
    final long eventTimeMillis = eventTimeNanos / 1_000_000L;
    final long elapsedTimeDiff = elapsedRealTimeMillis - eventTimeMillis;
    final long upTimeDiff = upTimeMillis - eventTimeMillis;
    final long currentTimeDiff = currentTimeMillis - eventTimeMillis;

    // Default case (elapsedRealTime, following the documentation)
    if (Math.abs(elapsedTimeDiff) <= Math.min(Math.abs(upTimeDiff), Math.abs(currentTimeDiff))) {
        final long bootTimeMillis = currentTimeMillis - elapsedRealTimeMillis;
        return bootTimeMillis;
    }

    // Other seen case (currentTime, e.g. Nexus 4)
    if (Math.abs(currentTimeDiff) <= Math.abs(upTimeDiff)) {
        return 0;
    }

    // Possible case, but unknown if actually used by manufacturers (upTime)
    throw new IllegalStateException("The event.time seems to be upTime. In this case we cannot use a static offset to calculate the Unix timestamp of the event");
}

Registration time delay

  • This code is independent of the latency between the event.time and the time at which the sensor event listener is triggered (registration time) as we only use the SystemClock to calculate the offset.
  • This allows to synchronize the sensor data between multiple devices if their system time is synchronized (there are apps for this).

Regarding "Possible Case" (see code):

  • It's unknown if any manufacturer actually uses the upTime as event.time . Thus, we throw an exception to see if this actually ever happens.

  • If this happens and if we calculate a static offset between currentTime and upTime this would lead to time shifts when the device is in (deep) sleep again. We would need to calculate the offset dynamically for each event which is quite heavy.

  • If this happens on devices this could be tested using: https://developer.android.com/training/monitoring-device-state/doze-standby#testing_doze_and_app_standby

https://source.android.com/devices/sensors/hal-interface.html#sensors_event_t
"timestamp must be synchronized with the elapsedRealtimeNano clock" so

val timeInMills = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000

I had the same problem and used ehartwell's solution . However I used System.currentTimeMillis() instead of new Date().getTime() .

Furthermore I found that there is an offset of sensorEvent.timeStamp and System.nanoTime() of maximal 300 ms, mostly < 200 ms. Depending on the needed accuracy you can ignore this difference.

If I use Boban S. solution , the difference is correct at the initialisation. However, the correct time and the time of the measurements diverge. The estimated time of the measurements is in the future.

I see three ways to get millis (Kotlin)

val millis = Date().getTime() + (event.timestamp - System.nanoTime()) / 1000000L

val millis = System.currentTimeMillis() + (event.timestamp - System.nanoTime()) / 1000000L

val millis = System.currentTimeMillis() + (event.timestamp - SystemClock.elapsedRealtimeNanos()) / 1000000L

all three deliver same result, but when I want to see diff from calculated value to current time

val diff  = System.currentTimeMillis() - millis

I see 'diff' with value -359704905 ?

Log.d("diff", "" + event.timestamp + " - " + System.nanoTime())

diff: 541695268300000 - 181990403666592

diff: 541695277240000 - 181990405818592

diff: 541695286859000 - 181990411901592

diff: 541695296139000 - 181990412584592

diff: 541695305735000 - 181990415222592

So all suggested solution are not right

for me this simple way fits my needs

override fun onSensorChanged(sensorEvent: SensorEvent?) {
    val millis = System.currentTimeMillis()
}

It varies for each device. It could be based on epoch, time since boot, and CPU awake time. Best approach is to read all three, then see which one the timestamp is closest to, then convert based on the offset.

SensorEvent.timestamp is when the event happened, but it is an elapsed time since boot. It is not absolute time. We want to convert it into absolute time.

Reference: https://developer.android.com/reference/android/hardware/SensorEvent#timestamp

  1. We need all the entities in a similar unit. We are taking Millis here.
  2. We have three entities to use. a) System.currentTimeMillis() b) SystemClock.elapsedRealtime() and c) SensorEvent.timestamp

在此处输入图像描述

  1. If we use SystemClock.elapsedRealtimeNanos() , then we need to convert it into Millis as below:
val systemCurrentTimeMillis = System.currentTimeMillis()
val systemClockElapsedRealtimeMillis = TimeUnit.NANOSECONDS.toMillis(SystemClock.elapsedRealtimeNanos())
val sensorEventTimeStampMillis = TimeUnit.NANOSECONDS.toMillis(sensorEvent.timestamp)
  1. We need to find the difference between the systemCurrentTimeMillis , and systemClockElapsedRealtimeMillis as below:

在此处输入图像描述

val currentMinusElapsedRealtimeMillis = systemCurrentTimeMillis - systemClockElapsedRealtimeMillis
  1. Once we find the difference, we need to add sensorEventTimeStampMillis to it as below:

在此处输入图像描述 OR在此处输入图像描述

val actualEventTimeMillis = currentMinusElapsedRealtimeMillis + sensorEventTimeStampMillis
  1. Then, we need to convert the result into UTC as below (I am using Joda Time ):
val actualEventTimeUtc = DateTime(actualEventTimeMillis, DateTimeZone.UTC)

The actualEventTimeUtc is the absolute time when the event happened.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM