High frequency GSensor polling on HTC devices

Dec 23, 2009 at 12:55 PM
Edited Dec 23, 2009 at 12:57 PM

I recently noticed that if the GSensor on my Touch Pro2 is queried more than around about 25 times per second, it stops providing useful data back and just returns the most recent vector over and over again. As my project was updating at a higher frequency than this, it presented a bit of a problem.

I implemented a fix for this into my copy of the code, which I thought I'd share in case anyone else found it useful. This limits the GSensor polling to a maximum of 25 times per second, regardless of how frequently the GetGVector() function is called. If calls are within 1/25th of the last poll, the last-polled vector is returned without querying the sensor again. Once sufficient time has elapsed, the next call will actually interrogate the sensor.

The change requires the following variables to be added at class level to the HTCSensor.cs file:

        private GVector _lastVector;
        private int _lastSampleTicks;

Once these have been added, the GetGVector function can be modified as follows:


        public override GVector GetGVector()
            // The GSensor freezes up when inundated with requests.
            // Ensure that at least 1/25th of a second has passed since we were
            // last interrogated. If not, return the most recently retrieved value.
            if (Environment.TickCount - _lastSampleTicks < (1000 / 25) && _lastVector.Length != 0)
                return _lastVector;

            GVector ret = new GVector();
            HTCGSensorData data = GetRawSensorData();
            ret.X = data.TiltX;
            ret.Y = data.TiltY;
            ret.Z = data.TiltZ;
            // HTC's Sensor returns a vector which is around 1000 in length on average..
            // but it really depends on how the device is oriented.
            // When simply face up, my Diamond returns a vector of around 840 in length.
            // While face down, it returns a vector of around 1200 in length.
            // The vector direction is fairly accurate, however, the length is clearly not extremely precise.
            const double htcScaleFactor = 1.0 / 1000.0 * 9.8;

            // Store the timestamp and vector for the next call in case it is too quick
            _lastSampleTicks = Environment.TickCount;
            _lastVector = ret.Scale(htcScaleFactor);

            return ret.Scale(htcScaleFactor);

With this change in place my code now works perfectly. Even though the GSensor values returned by GetGVector are sometimes cached, this is not apparent at all in my application, and the freezing sensor results that I experienced before have gone.