Je développe des applications comme le podomètre Runtastic en utilisant le algorithme mais je n’obtiens aucune similitude entre les résultats.
mon code est le suivant:
public void onSensorChanged(SensorEvent event)
{
Sensor sensor = event.sensor;
synchronized (this)
{
if (sensor.getType() == Sensor.TYPE_ORIENTATION) {}
else {
int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;
if (j == 1) {
float vSum = 0;
for (int i=0 ; i<3 ; i++) {
final float v = mYOffset + event.values[i] * mScale[j];
vSum += v;
}
int k = 0;
float v = vSum / 3;
//Log.e("data", "data"+v);
float direction = (v > mLastValues[k] ? 1 : (v < mLastValues[k] ? -1 : 0));
if (direction == - mLastDirections[k]) {
// Direction changed
int extType = (direction > 0 ? 0 : 1); // minumum or maximum?
mLastExtremes[extType][k] = mLastValues[k];
float diff = Math.abs(mLastExtremes[extType][k] - mLastExtremes[1 - extType][k]);
if (diff > mLimit) {
boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k]*2/3);
boolean isPreviousLargeEnough = mLastDiff[k] > (diff/3);
boolean isNotContra = (mLastMatch != 1 - extType);
if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {
for (StepListener stepListener : mStepListeners) {
stepListener.onStep();
}
mLastMatch = extType;
}
else {
Log.i(TAG, "no step");
mLastMatch = -1;
}
}
mLastDiff[k] = diff;
}
mLastDirections[k] = direction;
mLastValues[k] = v;
}
}
}
}
pour enregistrer des capteurs:
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(
Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(mStepDetector,mSensor,SensorManager.SENSOR_DELAY_NORMAL);
dans l'algorithme, j'ai différents niveaux de sensibilité en tant que vide public
setSensitivity(float sensitivity) {
mLimit = sensitivity; // 1.97 2.96 4.44 6.66 10.00 15.00 22.50 33.75 50.62
}
sur différents niveaux de sensibilité, mon résultat est:
sensitivity rantastic pedometer my app
10.00 3870 5500
11.00 3000 4000
11.15 3765 4576
13.00 2000 890
11.30 754 986
Je ne reçois aucun modèle approprié pour correspondre à l'exigence. Selon mon analyse, cette application utilise Sensor.TYPE_MAGNETIC_FIELD
pour le calcul des pas s'il vous plaît laissez-moi savoir un algorithme afin que je puisse répondre à l'exigence.
La première chose à faire est de choisir un algorithme. Autant que je sache, il existe approximativement trois façons de détecter des étapes à l'aide d'accéléromètres décrites dans la littérature:
Utilisez le théorème de Pythagore pour calculer la magnitude du vecteur d’accélération de chaque échantillon à partir de l’accéléromètre. Filtre passe-bas du signal d'amplitude pour supprimer le bruit haute fréquence, puis rechercher des pics et des creux dans le signal filtré. Vous devrez peut-être ajouter des exigences supplémentaires pour supprimer les faux positifs. C’est de loin le moyen le plus simple de détecter les pas, c’est aussi le moyen utilisé par la plupart, sinon tous les podomètres ordinaires du type de ceux que vous pouvez acheter dans un magasin de sport.
Utilisez "comme dans (1) de Pythagore, puis transmettez le signal à travers une FFT et comparez la sortie de la FFT avec les sorties connues de la marche. Cela nécessite que vous ayez accès à une assez grande quantité de données de formation.
Introduisez les données de l'accéléromètre dans un algorithme utilisant une technique d'apprentissage automatique appropriée, par exemple un réseau de neurones ou une transformation en ondelettes numérique. Vous pouvez bien sûr inclure d'autres capteurs dans cette approche. Cela nécessite également que vous ayez accès à une assez grande quantité de données de formation.
Une fois que vous avez choisi un algorithme, vous voudrez probablement utiliser quelque chose comme Matlab ou SciPy pour tester votre algorithme sur votre ordinateur à l'aide des enregistrements que vous avez effectués sur les téléphones Android. Dump des données de l'accéléromètre sur un cvs fichier sur votre téléphone, enregistrez le nombre d’étapes qu’il représente, copiez le fichier sur votre ordinateur et exécutez votre algorithme sur les données pour voir si le nombre de pas est correct, afin de détecter les problèmes liés à l’algorithme et de les corriger. leur.
Si cela vous semble difficile, le meilleur moyen d'accéder à une détection de pas correcte est probablement d'attendre que davantage de téléphones soient livrés avec le compteur de pas intégré activé par KitKat.
https://github.com/bagilevi/Android-pedometer
j'espère que cela pourrait être utile
J'utilise la détection de pas dans mon instrument de marche. J'obtiens de bons résultats de détection de pas. J'utilise achartengine pour tracer les données de l'accéléromètre. Jetez un oeil ici . Ce que je fais:
Le point 3. est calculé:
Regardez cette image:
Ceci est ma réalisation. Il a été écrit il y a environ 1,5 à 2 ans. Et je ne me souviens vraiment pas de tout ce que j'ai écrit. Mais cela a fonctionné. Et cela a bien fonctionné pour mes besoins.
Je sais que c'est vraiment une grosse classe (certaines méthodes sont supprimées), mais peut-être que ça sera utile. Sinon, je vais juste enlever cette réponse ...
public class StepDetector implements SensorEventListener
{
public static final int MAX_BUFFER_SIZE = 5;
private static final int Y_DATA_COUNT = 4;
private static final double MIN_GRAVITY = 2;
private static final double MAX_GRAVITY = 1200;
public void onSensorChanged(final SensorEvent sensorEvent)
{
final float[] values = sensorEvent.values;
final Sensor sensor = sensorEvent.sensor;
if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
{
magneticDetector(values, sensorEvent.timestamp / (500 * 10 ^ 6l));
}
if (sensor.getType() == Sensor.TYPE_ACCELEROMETER)
{
accelDetector(values, sensorEvent.timestamp / (500 * 10 ^ 6l));
}
}
private ArrayList<float[]> mAccelDataBuffer = new ArrayList<float[]>();
private ArrayList<Long> mMagneticFireData = new ArrayList<Long>();
private Long mLastStepTime = null;
private ArrayList<Pair> mAccelFireData = new ArrayList<Pair>();
private void accelDetector(float[] detectedValues, long timeStamp)
{
float[] currentValues = new float[3];
for (int i = 0; i < currentValues.length; ++i)
{
currentValues[i] = detectedValues[i];
}
mAccelDataBuffer.add(currentValues);
if (mAccelDataBuffer.size() > StepDetector.MAX_BUFFER_SIZE)
{
double avgGravity = 0;
for (float[] values : mAccelDataBuffer)
{
avgGravity += Math.abs(Math.sqrt(
values[0] * values[0] + values[1] * values[1] + values[2] * values[2]) - SensorManager.STANDARD_GRAVITY);
}
avgGravity /= mAccelDataBuffer.size();
if (avgGravity >= MIN_GRAVITY && avgGravity < MAX_GRAVITY)
{
mAccelFireData.add(new Pair(timeStamp, true));
}
else
{
mAccelFireData.add(new Pair(timeStamp, false));
}
if (mAccelFireData.size() >= Y_DATA_COUNT)
{
checkData(mAccelFireData, timeStamp);
mAccelFireData.remove(0);
}
mAccelDataBuffer.clear();
}
}
private void checkData(ArrayList<Pair> accelFireData, long timeStamp)
{
boolean stepAlreadyDetected = false;
Iterator<Pair> iterator = accelFireData.iterator();
while (iterator.hasNext() && !stepAlreadyDetected)
{
stepAlreadyDetected = iterator.next().first.equals(mLastStepTime);
}
if (!stepAlreadyDetected)
{
int firstPosition = Collections.binarySearch(mMagneticFireData, accelFireData.get(0).first);
int secondPosition = Collections
.binarySearch(mMagneticFireData, accelFireData.get(accelFireData.size() - 1).first - 1);
if (firstPosition > 0 || secondPosition > 0 || firstPosition != secondPosition)
{
if (firstPosition < 0)
{
firstPosition = -firstPosition - 1;
}
if (firstPosition < mMagneticFireData.size() && firstPosition > 0)
{
mMagneticFireData = new ArrayList<Long>(
mMagneticFireData.subList(firstPosition - 1, mMagneticFireData.size()));
}
iterator = accelFireData.iterator();
while (iterator.hasNext())
{
if (iterator.next().second)
{
mLastStepTime = timeStamp;
accelFireData.remove(accelFireData.size() - 1);
accelFireData.add(new Pair(timeStamp, false));
onStep();
break;
}
}
}
}
}
private float mLastDirections;
private float mLastValues;
private float mLastExtremes[] = new float[2];
private Integer mLastType;
private ArrayList<Float> mMagneticDataBuffer = new ArrayList<Float>();
private void magneticDetector(float[] values, long timeStamp)
{
mMagneticDataBuffer.add(values[2]);
if (mMagneticDataBuffer.size() > StepDetector.MAX_BUFFER_SIZE)
{
float avg = 0;
for (int i = 0; i < mMagneticDataBuffer.size(); ++i)
{
avg += mMagneticDataBuffer.get(i);
}
avg /= mMagneticDataBuffer.size();
float direction = (avg > mLastValues ? 1 : (avg < mLastValues ? -1 : 0));
if (direction == -mLastDirections)
{
// Direction changed
int extType = (direction > 0 ? 0 : 1); // minumum or maximum?
mLastExtremes[extType] = mLastValues;
float diff = Math.abs(mLastExtremes[extType] - mLastExtremes[1 - extType]);
if (diff > 8 && (null == mLastType || mLastType != extType))
{
mLastType = extType;
mMagneticFireData.add(timeStamp);
}
}
mLastDirections = direction;
mLastValues = avg;
mMagneticDataBuffer.clear();
}
}
public static class Pair implements Serializable
{
Long first;
boolean second;
public Pair(long first, boolean second)
{
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object o)
{
if (o instanceof Pair)
{
return first.equals(((Pair) o).first);
}
return false;
}
}
}
Une différence principale que j'ai remarquée entre votre implémentation et le code dans le projet grepcode est la façon dont vous enregistrez l'écouteur.
Votre code:
mSensorManager.registerListener(mStepDetector,
mSensor,
SensorManager.SENSOR_DELAY_NORMAL);
Leur code:
mSensorManager.registerListener(mStepDetector,
mSensor,
SensorManager.SENSOR_DELAY_FASTEST);
C'est une grande différence. SENSOR_DELAY_NORMAL
est destiné aux changements d’orientation et n’est donc pas si rapide (vous avez déjà remarqué qu’il faut un certain temps entre la rotation de l’appareil et la rotation réelle de l’appareil? C’est une fonctionnalité qui ne nécessite pas forcément une serait probablement assez ennuyant même). Le taux auquel vous obtenez des mises à jour n'est pas si élevé).
D'autre part, SENSOR_DELAY_FASTEST
est destiné à des choses comme les podomètres: vous voulez que les données du capteur soient aussi rapides et fréquentes que possible, afin que vos calculs de pas soient aussi précis que possible.
Essayez de passer à la SENSOR_DELAY_FASTEST
taux, et tester à nouveau! Cela devrait faire une grande différence.