The problem:
I need to synchronize some data set time-stamped using System.nanoTime() with another one time-stamped using SensorEvent.timestamp.
Description:
I am working on System Identification of a quadcopter. Data acquisition is done using Android API. The input to my system is the pulse width modulation (PWM) which are time-stamped using System.nanoTime() with a frequency of 200 Hz.
The output of the system is Androids's sensors measurements which are time-stamped using SensorEvent.timestamp.
I've checked many online resources but unfortunately didn't help. Can I access SensorEvent.timestamp whenever I want so I time-stamp the inputs using this clock?
I'm afraid this problem is a bit complicated. SensorEvent.timestamp switched from being System.nanoTime() to SystemClock.elapsedRealtimeNanos() at some point, but it is unclear when that happened in terms of devices and API levels. In fact, it appears to be completely manufacturer-dependent: https://code.google.com/p/android/issues/detail?id=56561
Furthermore, these clocks count relative to different events or points in time, and nanoTime() does not necessarily continue counting in deep sleep mode; Android: time intervals with deep sleep (System.nanoTime(), System.currentTimeMillis(), SystemClock.elapsedRealtimeNanos())
The only way we found to solve the problem is to periodically record System.currentTimeMillis(), System.nanoTime() and SystemClock.elapsedRealtimeNanos() as atomically as possible, and use the offset between SensorEvent.timestamp and both System.nanoTime() and SystemClock.elapsedRealtimeNanos() to figure out which one the sensor is using. Once you have that you can get an absolute timestamp for each sensor event adding the delta between your SensorEvent.timestamp and System.nanoTime() or SystemClock.elapsedRealtimeNanos() (respectively) to your System.currentTimeMillis(). It's not perfect, and could be off by as much as a few millisecond, but it's as good as we could get it.
Hope that helps!
Related
how can i get a clock-independent timestamp to count elapsed days and hours from specific timestamp ?
below methods do not work :
system.currenttimemillis //doesn't work it changes when wall clock gets changed
system.nanotime //maybe better choice than above one .maybe work(correct?)
system.elapsedrealtime //not works,if user boots up the phone
also i dont want to use NTP
I do not think that Android supports what you want - your use case seems to beg for NTP.
Also I do not think System.nanoTime() would work because(taken from here):
uptimeMillis() is counted in milliseconds since the system was booted. This clock stops when the system enters deep sleep (CPU off, display dark, device waiting for external input), but is not affected by clock scaling, idle, or other power saving mechanisms. This is the basis for most interval timing such as Thread.sleep(millls), Object.wait(millis), and System.nanoTime().`
I'm trying to synchronize the timestamps between multiple Android devices so I can kick off a task at the same time. I figure that I can use Timer and set a Date based on System.currentTimeMillis(), but the problem seems to be that the timestamps of multiple devices are just far enough apart from each other that I'm not getting the precision I want.
I'm looking at somewhere in the range of 50-100 ms, if possible. One idea I had was to use Android Beam to send one device's timestamp to the other device and then calculate a delta, but it turns out that I have to get the timestamp before the message is actually sent and received (i.e., the longer a user waits to send, the bigger the delta will be), which makes that scheme completely fall apart.
How can I sync up two or more devices so that their internal clocks will be no more than 100 ms apart from each other? Is this even possible without using an external server that keeps time?
Any other suggestions for techniques to do something across multiple devices as close to simultaneously as possible would also be welcome.
Why not use the GPS time? The time tags from GPS are pretty accurate.
You could agree on all devices on a certain time and then start it when the GPS tells you to.
Essentially, you have two choices: the simple way or the hard way.
The simple way is to use a single external source for time signals, such NIST, another internet source, or GPS as #Stefan suggests. Internet sources use NTP, see this Java NTP client question.
The hard way is to do Clock synchronization between the devices.
Android GPS hardware generally have only seconds precision. The three last timestamp digits of milliseconds float number are 000.
I am struggling with the same issue right now. I tried gps time, but I cannot guarantee that the user will have gps signal indoors.
My solution was to have all devices retrieve the time from a nist server and then just add or subtract the time difference with System.currentTimeMillis()
If the devices are rooted you could try to sync the clocks.
https://play.google.com/store/apps/details?id=ru.org.amip.ClockSync&hl=en
I'm writing an app that extends the SensorEventListener interface to listen for changes to the barometer, which I log in a logfile. Before I start logging, I prepend a system time in milliseconds (let's call this Millisecond Timestamp 1, or MT1), and after the logging is finished, I append another system timestamp in milliseconds (let's call this Millisecond Timestamp 2, or MT2).
The SensorEvent has its own timestamp (which I will call Nanosecond Timestamps, or NT), which I also log, between MT1 and MT2.
The problem is this: If the phone goes to sleep during the logging, the SensorEvent rate seems to no longer occur at the rate which I set (for example, SENSOR_DELAY_FASTEST). Furthermore, even though the SensorEvent timestamp is supposed to represent the nanoseconds of uptime since the phone has been rebooted, there are "missing" nanoseconds--the time gap between MT2 and MT1 is often twice or more that between NTN (where N is the number of samples) and NT1.
I've been able to sort of resolve this issue by using PowerManager.Wakelock(), but that results in my app being a huge power hog and seems like a really clumsy hack. Is there any other way to work around this problem?
Sensors are not guaranteed to work if the device goes to sleep, or even if the screen turns off (but the CPU has not necessarily yet powered down). The behavior is undocumented and definitely seems to vary by device.
Either settle for being "a huge power hog" or redesign your app to not require sensor readings except when the screen is on.
Sensors in Android are definitely designed to be used actively by foreground apps, not for long-term logging or monitoring purposes.
Is there a way to synchronize the timestamps in values meassured by Sensors (e.g. acceleration) (SensorEvent.timestamp) and GPS (Location.getTime()).
SensorEvent.timestamp are the nanoseconds since the device has been booted (local time). Location.getTime() are the miliseconds since1970 (global time).
One solution I had in mind was to calculate the offset between the local time and the global (GPS) time. But the problem is, that the time in Location is the time when the GPS-message arrived at the device, but it takes some time until the GPS-unit (don't know how it is called) of the device calculates the position and forwards it to my application, so I can't calculate at what local time the message arrived. I've read somewhere (can't remember where) that the delay from arrival of the message until it has been processed can be several 100 miliseconds, so I will always have a high offset between GPS-data and data from other sensors, if I algin the local time when the app gets the location-message and the timestamp in the location.
Is there a way to figure out how long it takes exactly to process the GPS-message? Or is there another way to synchronize the meassurements?
The reason why I want to synchronize the values is, that i want to apply a filter (e.g. Kalman-Filter) on the data. For this I want to calculate the offset between a sensor value and a gps-value as exact as possible.
Usually Pulse Per Second (PPS) signals are used to link the time of measurement to the local clock. The GPS receiver toggles a pulse at the moment of measurement. This pulse is then timestamped using the local clock. On Android phones, this is not available.
In addition to the delay caused by processing and transmission time, there might be additional delays caused be filtering in the GPS software. This delay may even be depending on the speed or number of satellites used.
You might be able to 'calibrate' the delay between GPS data and your sensor data by comparing signals from both. E.g.: If you go from accelerating to decelerating, you will see this clearly in you phone's accelerometer and the GPS speed. However, I doubt if you can get a good accuracy for the delay.
You could even add a state in you Kalman filter which estimates the delay.
I would like to get some help about getting 3G data statistics between a date interval.
As far as I know, I should use TrafficStats (Android api 2.2 or higher). I would like to save this information into a SQLite table to show statistics for apps monthly:
Interval date: 01/01/2012 - 31/01/2012
Google Maps - 1,5 Mb
Google Talk - 0,9 Mb
Facebook app - 5,6 Mb
So, I Think I should use a background service. Is this the best way? How should I try to do it in the background service? How do you think I should save the information in SQLite?
(#Pabloku, sorry this answer is coming so late, hopefully it will still be of some help)
Firstly, if you're looking to get traffic stats for individual apps, but only on 3G, it's not possible using public APIs. Android provides the TrafficStats.getUidTxBytes(int) and TrafficStats.getUidRxBytes(int) as public APIs to get the total number of bytes used by apps, but nothing (public) to separate them by interface.
Assuming this doesn't ruin your day, here is a pseudocode algorithm for how to do the rest of what you mention:
Set an alarm if necessary (using AlarmManager) for the start of your range, and store these values (presumably in a DB). Reason: you may need to subtract these existing TrafficStats values as an offset if they are > 0 at the time your date range starts.
Also set an alarm for the end of your range.
Create a BroadcastReceiver to receive ACTION_SHUTDOWN.
In your BroacastReceiver, note down the TrafficStats for your app(s) at shutdown. Reason: TrafficStats will get reset on every reboot.
If this is the first shutdown since start: subtract your initial offset and store that final value (being careful to remove the initial offset)
Otherwise, whatever value is reported will be accurate since boot.
Once your end alarm is triggered, note down the TrafficStats at that point, and add all previously collected stats
(if somehow the phone never rebooted between start and end, just do endStats - startStats).
Good luck!