Moyenne glissante signal particulier

Bonjour,

Tout d'abord, désolé si je ne suis pas dans la bonne partie du forum, je n'ai pas trouvé l'utilisation très intuitive...

Je cherche depuis quelques jours à enlever des valeurs aberrantes reçues par mon capteur boussole électronique et à faire une moyenne glissante sur les valeurs conservées.

Celui-ci m'envoi des données entre -180 et +180 et peut passer de -180 à +180. J'arrive à enlever les valeurs aberrantes et à faire une moyenne glissante sur les 10 dernières valeurs , mais parfois mon capteur se situe entre -175 et +175 ( ex : {-176,-177,+179,+175,-178,-176,-177,+179,+175,-178} du coup ma moyenne est de -35,4 et donc pas du tout entre -175 et 175.

Je sais que c'est un problème de math, mais crois que mes cours sont trop loin...

Merci pour votre aide.

Une solution, il y a peut être mieux:

Ce cas va se présenter si il y a des données inférieures à -150 et des données supérieures à +150.
Dans ce cas, rajouter 128 à toutes les valeurs, faire la moyenne, puis retrancher 128 à la valeur calculée.

Une moyenne ne fonctionne pas quand on est en arithmétique sur des angles car -178° est plus proche de +178° que de 0° .

On peut ajouter 360° Aux valeurs négatives et moyenner. Par exemple pour trois valeurs -178, + 178 et 180
(-178+360) + 178 + 180 = 540 ➜ moyenne = 180°
(On obtient une réponse entre 0° et 360°)

Une autre solution consiste à représenter chaque angle Ai par son cosinus (X i) et sinus (Y i) qui sont des projections sur les axes horizontal et vertical du cercle trigonométrique. Ensuite vous faites la moyenne de chacune des projections et retournez à un angle moyen par l’appel de
atan2(Y moyen, X moyen);

Par exemple pour trois valeurs -178, + 178 et 180
-178 (x= -0.9994; y=-0.0349)
+178 (x=-0.9994; y +0.0349)
+180 (x=-1; y=0)
Moyenne des X = -0.9996
Moyenne des Y = 0
angle moyen = atan2(0, -0.9996) = 3.1415926 radians = environ 180° Ce qui est bien la valeur attendue

Sinon Si vous lisez ce fil [HMC5883L] Fixer des limite pour le servo - #12 by J-M-L, j’avais proposé une fonction

int16_t angleCorrection( int16_t angleInitial, int16_t angleCourant )
{
  int16_t diff = ( angleCourant - angleInitial + 180 ) % 360 - 180;
  return diff < -180 ? diff + 360 : diff;
}

Qui donne la différence angulaire entre deux angles (plus petit déplacement signé pour aller du premier vers le second)

Si vous modifiez cette fonction pour utiliser des float et ajoutez au premier angle la moyenne des variations ainsi calculées ça vous donnera aussi une réponse

Avec le même exemple :
Entre -178 et +178 on obtient -4
Entre -178 et 180 on obtient -2

pour 3 valeurs donc la somme est -6 donc la moyenne est -2
Si on ajoute: -178-2 = -180° Ce qui semble aussi cohérent

Bonjour,

Tout d'abord, désolé si je ne suis pas dans la bonne partie du forum, je n'ai pas trouvé l'utilisation très intuitive...

Je cherche depuis quelques jours à enlever des valeurs aberrantes reçues par mon capteur boussole électronique et à faire une moyenne glissante sur les valeurs conservées.

Celui-ci m'envoi des données entre -180 et +180 et peut passer de -180 à +180. J'arrive à enlever les valeurs aberrantes et à faire une moyenne glissante sur les 10 dernières valeurs , mais parfois mon capteur se situe entre -175 et +175 ( ex : {-176,-177,+179,+175,-178,-176,-177,+179,+175,-178} du coup ma moyenne est de -35,4 et donc pas du tout entre -175 et 175.

Je sais que c'est un problème de math, mais crois que mes cours sont trop loin...

Merci pour votre aide.

bonsoir
plutôt un problème de référentiel

-180 +180 ° c'est 360° d'amplitude
il faut référencer ton angle d'entrée entre 0 et 360

angle_input = angle_lu+180

Merci pour la réponse.

J'y ai pensé et le problème sera le même : {355, 5, 6, 357, 3,359, 355, 5, 6, 357, 3,359}
La moyenne sera de 180,8 soit complètement l'opposé.
Il faudrait une solution genre transformer l'angle en radian, prendre le cos et le sin de l'angle, faire une moyenne glissante sur le cos et le sin et reconvertir en angle degré. Je ne sais même pas si ça fonctionnerai mais ça me paraît laborieux... Est-ce que l'arduino est capable de calculer ça?

Si il y a des mesures <-150 et des mesures >+150 alors:
Si le calcul est fait sur des octets: rajouter 128 à toutes les valeurs, faire la moyenne, retirer 128
Si le calcul est fait sur des int, pareil mais il faut rajouter au moins 300

Le calcul est fait sur des int.

Les valeurs peuvent être :
De -179 à 179 et
-177, -178, -179, 179, 178, ...

Du coup Ajouter ou soustraire un nombre quel qu'il soit ne résout pas le problème (enfin sinon je n'arrive pas à comprendre pourquoi?), il ne fait que le décaler. Le problème se pose parce qu'on peut passer de 0 à 360 ou de 6179 à 179 ou de 360 à 720... Le système classique de calcul de moyenne ne fonctionne pas dans ce cas là bien précis.

J'erreuré umanum est:

Si il y a des mesures <-150 et des mesures >+150 alors:
rajouter 360 à tous les nombres négatifs, faire la moyenne, et si la moyenne dépasse 180, retirer 360

-177, -178, -179, 179, 178
va donner:
183, 184, 185, 179, 178
Moyenne: 182 soit -178

Si tu veux une explication du pourquoi?

1 Like

Je n'ai pas compris pourquoi mais je vais y réfléchir ce soir. Le poser sur du papier va m'aider.

Si je n'arrive pas à trouver pourquoi je te solliciterai demain.

En tous cas, pour votre aide si rapide!!

Bonne soirée.

Je vais supposer que 180 existe, mais pas -180 sinon il faut se poser la question c'est quoi la différence.

Les valeurs sont sur un cercle continu:
image
-179 et 180 sont à côté

Quand on passe ces valeurs dans un int, on déplie et on obtient:

les valeurs -179 et +180 ne sont plus à côté.

Si on moyenne sur un intervalle qui ne passe pas par la limite, déplier le cercle ne change rien. Pa contre si on a des valeurs de par et d'autre de la limite, lorsque l'on déplie, il fau par exemple déplier ailleurs. Rajouter 360 recopie les valeurs négatives de l'autre côté à droite:

On retrouve les valeurs proches et la moyenne est faisable.

J’ai fusionné deux topics identiques. Noter que je propose 3 approches en réponse 3 maintenant

@chrismaximilien merci de ne pas faire de double posts.

On cherche à faire une moyenne arithmétique entre plusieurs valeurs. En passant les coordonné par les fonctions trigonométriques qui ne sont pas linéaires, la moyenne obtenue n'a plus rien d'arithmétique. On obtient sans doute une valeur comprise entre les extrémums, mais rien ne dit qu'elle est arithmétique.

Cela ne se voit peut être pas si les angles sont très proche, mais il suffit de prendre des angles plus grands pour voir le hic.

Soit les angles: 0°, 90° et 90°. On a:
0° (x=1; y=0)
90° (x=0; y=1)
90° (x=0; y=1)
moyenne: x=0.3333; y=0.6667
atan2(0.3333, 0.6667)=63°
On est bien entre les valeurs, mais pas sur la moyenne de 60°

Plus amusant:

Soit les angles: +90°, +90°, +90°, +90°, +90°, +90°, +90°, +90°, +90°, +90°, +90°, -90°, -90°, -90°, -90°, -90°, -90°, -90°, -90°, -90°, -90°. (11 valeurs à +90°, 10 valeurs à -90°)
On a:
+90° (x=0; y=1)
-90° (x=0; y=-1)
moyenne: x=0; y=+1/11
atan2(0, 0.0909)=+90°
Valeurs attendue: 90°/21=4°
Si on change une seule valeur +90° en -90°, on obtient -90°

Les autres méthodes sont meilleures, d'autant plus que passer par les réels est plus cher...

Ne passe pas non plus pour -1°, 0°, +1°:
Cela ferait moyenne(359, 0, 1)= 120°
Valeur attendue 0°
C'est possible que si on est du côté de la cassure(voir post #9 et #12)

Reste en lice la troisième méthode du post#3 et celle du post#9. Celle du post#3 semble plus longue en terme de temps et de code, mais est peut être mieux (pas à choisir si on ajoute ou pas 360°)

Bonjour,
Je n'ai pas bien suivi la discussion mais si on a une série de valeurs brutes. On peut éventuellement éliminer les valeurs "aberrantes". Si on place ces données dans une pile FIFO fixe et on fait la moyenne des valeurs de la pile.
Moyenne = somme des valeurs de la pile / nombre de valeurs

@icare oui, mais justement, c'est la moyenne qui pose problème car elle se produit sur des valeurs voisines du point de vue angulaire mais disjointes du point de vue mathématique.

On est pas toujours tenu de trouver une solution générale.
Il suffit de vérifier si les valeurs franchissent la frontière ±180° et changer de formule dans ce cas particulier.

Maintenant, le bruit sur la mesure semble relativement important, il y a aussi peut-être du travail à faire sur le magnétomètre. Même si ça ne résoudra jamais le problème du passage de la frontière ±180°.

Donc un pré-traitement de la données.

On fait d’abord le modulo 360 donc ça fait bien 0

De manière plus générale si les valeurs ne sont pas proches alors la notion de moyenne ne veut rien dire et ce ne sera jamais pertinent

C’est souvent discuté pour mesurer la direction du vent sur les girouettes si vous avez un vent de nord suivi d’une bourrasque du sud vous ne pouvez pas dire qu’il y a un vent d’est ou d’ouest (qui serait la moyenne)

Ce n’est donc pas la peine d’essayer de résoudre ce cas