class stepDetector
{
void activate()
{
int h = 480;
offset = h * 0.5f;
scale = - (h * 0.5f * (1.0f / (MAGNETIC_FIELD_EARTH_MAX)));
MagnetometerRefresh();
}
void deactivate()
{
MagnetometerDisable();
}
void sensitivity(float value) // lower is more sensitive, default is 3
{
limit = value;
}
bool update()
{
bool result = false;
// Device rotation also cause acceleration. To counter
// this, rotation is measured with the magnetometer.
Vec magValue = Magnetometer();
// Distance compared to the previous update
magDist[magDistPtr] = Dist(magValue, lastMagValue);
lastMagValue = magValue;
// When 5 point average > 0.6 or current value > 1,
// the device is rotated.
if(getMagAverage() > 0.6 || magDist[magDistPtr] > 1.0)
{
magDistPtr++;
if(magDistPtr == 5) magDistPtr = 0;
return result;
}
magDistPtr++;
if(magDistPtr == 5) magDistPtr = 0;
// To avoid double triggers, a sleep period of 0.3 seconds
// is added after a step
if(sleep > 0)
{
sleep -= Time.ad();
return result;
}
// don't do anything if the value hasn't changed
Vec accValue = Accelerometer();
if(accValue != lastAccValue)
{
// this part is based on code found at:
// https://github.com/bagilevi/android-pedometer/blob/master/src/name/bagi/levente/pedometer/StepDetector.java
lastAccValue = accValue;
float calc = 0;
calc += offset + accValue.x * scale;
calc += offset + accValue.y * scale;
calc += offset + accValue.z * scale;
calc /= 3;
// if the movement direction has changed, this is a strong indication
// of a step occurance
int direction = (calc > lastCalc ? 1 : (calc < lastCalc ? -1 : 0));
if(direction == -lastDirection)
{
// direction changed
int extType = (direction > 0 ? 0 : 1); // minimum or maximum?
lastExtremes[extType] = lastCalc;
float diff = Abs(lastExtremes[extType] - lastExtremes[1 - extType]);
if(diff > limit)
{
bool isAlmostAsLargeAsPrevious = diff > (lastDiff * 2 / 3);
bool isPreviousLargeEnough = lastDiff > (diff / 3);
bool isNotContra = (lastMatch != 1 - extType);
if(isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra)
{
// this counts as a step. Sleep for 0.3 seconds
result = true;
lastMatch = extType;
sleep = 0.3;
} else
{
lastMatch = -1;
}
}
lastDiff = diff;
}
lastDirection = direction;
lastCalc = calc;
}
return result;
}
// Helper function to get an average magnetometer value
float getMagAverage()
{
float result = 0;
for(int i = 0; i < 5; i++)
{
result += magDist[i];
}
result /= 10;
return result;
}
private:
C float MAGNETIC_FIELD_EARTH_MAX = 60.f;
// for accelerometer calculations
float limit = 3;
float lastCalc, lastDiff, scale, offset;
float lastExtremes[2];
int lastDirection ;
int lastMatch = -1;
Vec lastAccValue(0);
// for magnetometer calculations
Vec lastMagValue(0);
float magDist [5];
int magDistPtr = 0 ;
float sleep = 0;
}
stepDetector StepDetector;