Accelerometer Motorola Milestone

F

funk

Ambitioniertes Mitglied
2
Hey,

ich schlag mich mal wieder mit meiner Diplomarbeit herum und damit
speziell mit dem Accelerometer meines Milestones.

Jetzt wollte ich mal fragen, ob ihr das gleiche Phänomen bei euch
feststellen könnt (oder ob es grundsätzlich an meiner Physik-und-
Mathematik-Versteh-Resistenz liegt):

Wenn ich mein Milestone auf den Tisch lege bekomme ich Werte um die
X = 0,2
Y = 0,1
Z = 10,2

...soweit so gut; das kann ich für meine App auf X = 0 , Y = 0 und Z = 9,8
kalibrieren.

Wenn ich jetzt aber mein Milestone anhebe, habe ich Werte im Bereich von
Y = 6 und Z = 6 ! Abzüglich der Erdbeschleunigung würde das bedeuten,
dass das Halten des Milestone im (ca) 45° Winkel eine Beschleunigung von
2-3 m/s^2 bedeutet (Y+Z-G)....kann das sein?!?

Bin für jede Hilfe dankbar!

Gruß,
Frank
 
*hust*
Vektorrechnung: Länge des resultierenden Vektors = sqrt(x²+y²+z²), damit kommst du mit 0;6;6 auf 8,5.
Ansich sollte da allerdings 9.8 wieder rauskommen, kann aber daran liegen das die 6er wahrscheinlich gerundet waren, oder? ;)
Abzüglich der Erdbeschleunigung sollte auf dem Gerät beim Halten gar keine(!) Beschleunigung sein!
Wenn man etwas beschleunigt wird es nämlich schneller, ist klar oder? :p

Hoffe das hat ein wenig geholfen ;)
 
Ich würde gerne hinzufügen, das die in den geräten verbauten Chips so in etwa 1$
pro Kilo kosten, und weder besonders präzise noch rauscharm sind ;)
( und den gesamten Bereich von bis zu +-8G pro Achse teilen die in 256 Interwale )
 
Immerhin +-8G.
Die Wiimote schafft meine ich nur 3.

Aber danke für die Infos :)
 
Die Chips (wenn es sich um Bosch Sensortec BMxxxx handelt ) haben 3 umschaltbare Bereiche
( +-2 / 4 / 8 G ) - aber natürclih nicht für Android-Anwendung ;)
 
Ist ein ST Microelectronics LIS331DLH, aber von den Specs ist der
sehr nah am Bosch Sensortec dran...

@FelixL: jaja, die gute alte Vekorrechnung...bitter genug, dass die mir
Probleme bereitet! :)
Die Frage ist jetzt: wenn ich sqrt(x^2+y^2+z^2) rechne, dann bekomme
ich G heraus (ungefähr...im Messtoleranzbereich); ich möchte aber die
Beschleunigung nach vorne bekommen. Sehe ich das richtig, dass dann
eine Beschleunigung mit 3 m/s^2 mir ein Ergebnis von ca. 12,8 m/s^2
nach der Vektoraddition liefert?

Sorry, wenn ich hier Mittelstufen-Mathe nachfrage, aber ich bin mit
meinen Überlegungen mittlerweile gedanklich im Niemandsland angekommen...

Danke schon mal für die Antworten!

Gruß,
Frank

PS: Laut Datenblatt hat er die +- 8 G immerhin in 12 Bit und nicht nur in 8 Bit
wie bei anderen Sensoren...
 
ich möchte aber die
Beschleunigung nach vorne bekommen.
Was heißt "nach vorne"? Wirklich horizontal oder nur die Erdbeschleuigung rausgerechnet?
Muss aber selbst erst mal überlegen, wie ich das machen würde, egal welchen der beiden Fälle du meinst ...
Sehe ich das richtig, dass dann
eine Beschleunigung mit 3 m/s^2 mir ein Ergebnis von ca. 12,8 m/s^2
nach der Vektoraddition liefert?
Das schon mal nicht :p
Die reine Addition funktioniert nur, wenn du das Phone anhebst oder fallen lässt. Wenn eben deine Beschleunigungen in die selbe Richtung gehen wie die Erdbeschleunigung. Sonst musst du wieder Pytagoras machen, nur rückwärts. Allerdings brauchst du wahrscheinlich die zusätzliche Info wo unten ist...Sprich wenn sich das Gerät dreht während dem Beschleunigen, könnte es auch nochmal schwieriger werden. Kommt also wirklich drauf an, was du brauchst ;)
 
Puuh...also eigentlich ist das ganze der kleiner Teil meiner Dipl.Arbeit:

Ich hab in meiner Studienarbeit eine Lokalisierung über Schrittmustererkennung
mit einem Accelerometer (externer Sensor allerdings und Symbian Handy) gemacht.
Jetzt soll ich eine "Koppel"-Lokalisierung mit Accelerometer und Bluetooth machen.
Beim Accelerometer soll ich die zurück gelegte Strecke per Integration berechnen
...also wollte ich mal vom ganz einfachen fall s = 1/2 a*t^2 + v*t + s0 ausgehen.
Wenn ich laufe werde ich das Milestone der Länge nach vor mir halten.
Damit interessiert mich zunächst nur die Beschleunigung auf der Y-Achse (falls ich
das MS tatsächlich komplett parallel zur Erdoberfläche gehalten bekommen würde...)
und eben die Beschleunigung auf der Z-Achse....bzw. die Summe der Vektoren auf
der Y- und Z-Achse minus G.

Auf so Späßchen wie Orientierung über Tangens der Beschleunigung und ähnliches
bin ich bisher gar nicht eingegangen; allerdings weiß ich auch noch nicht, wie ich
in meiner Lokalisierung die Werte des Orientierungssensors (der glaube ich auch nur
Beschleunigungswinkel berechnet...) mit "einberechne"...

Gruß,
Frank
 
Aaalso. Interessantes Thema schonmal. Hab kurz gegoogelt, dead-reckoning hört sich an wie ein schlechter Zombie-Film :D

Hab jetzt noch schnell eine Skizze zu Papier gebracht (bei mir fallen gerade 2 Blöcke Uni aus :p)

Was wir ja oben schon gemacht haben, war, einen Vektor zu errechnen aus den drei. Damit hat man die Gesamtbeschleunigung auf dem Gerät. Wenn man jetzt einfach nur den Anteil will, der zur Erdbeschleunigung senkrecht ist, kann man die oben benutzte Formel umstellen.
Also erstmal nochmal
beschlGesamt=sqrt(x²+y²+z²)
Dann brauchen wir den Anteil, der senkrecht auf einem Vektor der Länge 9,81 diesen Vektor ergibt. Mal dir einfach mal ein Dreieck irgendwohin, in dem die längste Seite unsere Gesamtbeschleunigung ist, eine der kürzeren Seiten ist dann 9,81 und die dritte ist die, die senkrecht zur Erdbeschleunigung ist...also in der x-y-Ebene der realen Welt liegt. (Achtung, nicht den Unterschied zwischen x,y und z im Gerät und in der realen Welt aus den Augen verlieren!)
Pytagoras sagt a²+b²=c², bei uns sind c (=beschlGesamt) und a (Erdbeschleunigung g=9,81) bekannt. Umstellen gibt a²-c²=b²
beschlXY=sqrt(beschlGesamt²-g²)
Also sind es eigentlich nur 2 Formeln. Man kann sie auch zusammenfassen zu
beschlXY=sqrt(x²+y²+z²-g²)
Fehlerquellen bei dieser Formel:
1) Achtung, sobald das Gerät in Richtung hoch/runter beschleunigt wird, glaubt das Gerät, es wird zur Seite beschleunigt. Kannst das ja mal ausprobieren indem du es genau gerade hältst und das machst. Dummerweise fällt mir nichts ordentliches ein, um herauszufinden, wo wirklich unten ist. Das ging wahrscheinlich mit wenig Aufwand über den Magnetfeldsensor.
2) Du hast keine Richtung. Diese ließe sich aber (noch einfacher als bei 1)) über den Magnetfeldsensor machen.
3) Der Sensor hat natürlich Ungenauigkeiten.
4) Je nachdem wie du die Daten danach behandelst, entstehen hier weitere. Willst du einfach so oft wie möglich die gerade zurückgelegte Strecke über die Formel oben berechnen und dann zur Gesamtstrecke dazu addieren? Ich denke was besseres ist leider nicht möglich.

Cool wäre natürlich, wenn du das ganze über Google-Maps legst, die Strecke so oft wie möglich berechnest und dir dann über den Kompass die Richtung holst und direkt eine Linie in Google-Maps zeichnest.
Wegen 1) denk ich nochmal nach ;)

Edit: zu 1) Ne, Magnetfeld wird wahrscheinlich doch nichts bringen. Gyroskop wäre praktisch :D Besorg dir das nächste Motorola mit Gyroskop, dann ist das auch genau :D
 
Zuletzt bearbeitet:
Der Held, der seine (Uni-)Freizeit opfert! :D

Genau die Formel hatte ich auch schon mal dran stehen...genau genommen könnte man
sogar den X-Anteil der Gesamtbeschleunigung vernachlässigen (glaub ich), also

Code:
Math.sqrt(Math.pow(y_calib, 2.0)) + Math.pow(z_calib, 2.0) - Math.pow(SensorManager.GRAVITY_EARTH, 2.0));

wobei y_calib und z_calib die y- und z-Werte des Accelerometers minus
eines Kalibrierungswertes sind (damit y tatsächlich null und z tatsächlich
G misst wenn das Milestone flach auf dem Tisch liegt).

Das Ganze werd ich dann auf einer .svg-Grafik einzeichnen lassen (müssen).
Da wird dann ein Punkt eingezeichnet und die Grafik, die unterliegt (also
der Grundriss des Raums) wird dann eben verschoben um -(sin alpha * c) in
x- und um -(cos alpha * c) in y-Richtung (x und y des Screens des Milestones).

Oder so ähnlich...
 
OK, irgendwo in meinem Code hängt tierisch der Wurm drin:

wenn das Milestone flach liegt, wird die Geschwindigkeit richtig ausgegeben,
aber die Strecke wird auch bei Geschwindigkeit = 0.0 immer größer (ansich
logisch, aber das geht in 10 cm Schüben...das ist zuviel für Sensor-Drift).
Wenn ich das Milestone anhebe, kommt sowohl für Strecke als auch für
Geschwindigkeit der Wert NaN und ich weiß nicht, wo in meiner Berechnung
der Fehler liegt...es sollten immer noch Werte sein!

Hier mal mein Code-Schnippsel
Code:
private Runnable TimeDistanceRule = new Runnable() {
         public void run() {
// cx, cz und cy sind die Kalibrierungswerte wenn das Milestone flach auf dem Tisch liegt
            x_calib = x_double + cx;
            y_calib = y_double + cy;
            z_calib = z_double + cz;
            current_time = System.currentTimeMillis();

// start_time ist die Systemzeit zur Zeit der Kalibrierung
            temp_time = current_time - start_time;
            temp_time_secs = (double) (temp_time) / 1000;
            
// Das ist jetzt mal nur der Test mit der Vektoraddition, der hier im Thread besprochen wurde
            vector_sum = Math.sqrt(Math.pow(y_calib,2.0) + Math.pow(z_calib,2.0));
// Hier die Berechnung nach FelixL
            temp_accel_value = Math.sqrt(Math.pow(y_calib, 2.0) + Math.pow(z_calib, 2.0) - Math.pow(SensorManager.GRAVITY_EARTH, 2.0));
            
// Eine Formatierung, damit die Beschleunigungen nicht mit 10 Nachkommastellen ausgegeben werden
            NumberFormat nf = NumberFormat.getNumberInstance();
            nf.setMinimumFractionDigits(2);
            nf.setMaximumFractionDigits(3);
            formatted_v = nf.format(Geschwindigkeit);
            formatted_d = nf.format(Strecke);
            
/* Ein Möchte-Gern-Low-Pass-Ghetto-Filter...bei Werten im Bereich des Sensor-Drifts soll die Geschwindigkeit als "0" gesetzt werden; die Distanz wird trotzdem - der mathematischen Korrektheit wergen - berechnet */
            if (y_calib < 0.1 && y_calib > -0.1){
                Geschwindigkeit = 0.0;
                temp_distance = 0.5 * temp_accel_value * Math.pow(temp_time_secs, 2.0) + Geschwindigkeit * temp_time_secs;
            }    
// Noch ein "Filter" der Sensor-Drift abfangen soll
            else if (Math.abs(temp_accel_value - temp_accel_old) < 0.1){
                // do nothing
            }
// Das Weg-Zeit-Gesetz bzw. eine Integration nach Zeit der Beschleunigungswerte zur Geschwindigkeits- und Distanzberechnung
            else {
                Geschwindigkeit = temp_accel_value * temp_time_secs + temp_velocity;
                temp_distance = 0.5 * temp_accel_value * Math.pow(temp_time_secs, 2.0) + Geschwindigkeit * temp_time_secs;
            }
            
            temp_velocity = Geschwindigkeit;
            temp_accel_old = temp_accel_value;
            Strecke += temp_distance;
            start_time = current_time;
            
            yVelocity.setText(getString(R.string.velocity) + ": " + formatted_v + " m/s");
            yDistance.setText(getString(R.string.distance) + ": " + formatted_d + " m");
            VecSum.setText(getString(R.string.vector) + ": " + vector_sum);
            
            TempTime.setText(getString(R.string.time) + ": " + temp_time_secs + " s");
            SensorCalibration.setText(getString(R.string.calibration) + String.format(": %+2.5f | %+2.5f | %+2.5f", cx, cy, cz));
            
// Ein Handler, der die Funktion alle 100ms aufruft    
            mHandler.postDelayed(this, 100);
         }
    };
Bin mal wieder über jede Korrektur froh..

Gruß,
Frank
 
O man, ich merk gerade dank dir, dass ich einen Denkfehler drin hatte .

Eigentlich musst du die Beschleunigung in der x-y-Ebene, die wir bis jetzt haben, dann wieder aufteilen in x(global) und y(global), mithilfe des Magnetfeldsensors. Dann die Formel mit s=(a/2)*t²... einzeln anwenden. Sonst kannst du nur gerade Strecken laufen. Außerdem kannst du dann das Milestone auch drehen. Vorher hätte das Fehler verursacht.

Formeln für das "Entdrehen" kommen gleich ;)

Edit: Ich schau erst mal über den Code drüber.
 
Zuletzt bearbeitet:
Aaalso.
1) Willst du nicht nach
if (y_calib < 0.1 && y_calib > -0.1){
y_calib auf 0 stellen? Du stellst "Geschwindigkeit" auf Null, nur weil die Beschleunigung gleich null ist. Das Objekt behält seine Geschwindigkeit aber bei, (gerade) wenn keine Beschleunigung wirkt!
Da alles danach else if oder else ist springst du raus und setzt direkt temp_velocity=Geschwindigkeit== 0
Willst du das so? ^^
2) formatted_v = nf.format(Geschwindigkeit);
Das habe ich noch nie benutzt. Ändert sich formatted_v immer mit wenn sich "Geschwindigkeit" ändert?
3) temp_distance = 0.5 * temp_accel_value * Math.pow(temp_time_secs, 2.0) + Geschwindigkeit * temp_time_secs
Hier musst du definitiv nicht die Zeit seit der Initialisierung nehmen, sondern seit der letzten Berechnung! Kannst ja mal fest 100 ms nehmen, wenn dein Handler dieses Intervall nutzt.
4) Da ich mit Beschleunigung noch nichts gemacht habe noch eine Frage:
enthält x_double immer den aktuellen Wert? Wird der woanders aktuallisiert? Ist für mich hier leider nicht ersichtlich, ich denke mal du hast dran gedacht ;)
5) Ich würde das vielleicht ganz anders aufbauen
a) Initialisierung, so wie bei dir
b) Filter für die Beschleunigungswerte. Wahrscheinlich nicht nötig, vielleicht kannst du es später mal ohne probieren aber man kann ja mal:
if (y_calib < 0.1 && y_calib > -0.1){
y_calib == 0;
}
Das selbe für x und z
c) temp_accel_value = ...
Hier am besten auch x wieder mit rein nehmen.
d) Dann erst die Strecke, und später die Geschwindigkeit
Strecke += 0.5 * temp_accel_value * Math.pow(0.1, 2.0) + temp_velocity*0.1;
e) Geschwindigkeit würde ich umbennen in velocityChange
velocityChange = temp_accel_value*0.1 //0.1 wegen den 100ms des Handlers. Später dynamisch!
f) temp_velocity+=velocityChange
 
Danke erstmal fürs drüber schauen!!

zu 1)
wenn ich y_calib = 0 setze "verfälsch" ich mir ja quasi die wahren Ergebnisse,
oder? Es soll nur eben keine Geschwindigkeit berechnet werden, da 0,1 m/s^2
von mir jetzt mal plump als Drift/Messfehler/Sensorungenauigkeit deklariert
wurden um ein anständiges Ergebnis zu erzielen
damit ist dann auch meine Geschwindigkeit vx (v zum zeitpunkt x) = 0...allerdings
sind meine else if und else klauseln vielleicht eher quatsch

zu 2)
ja, nf.format erzeugt ja nur einen string mit 2 nachkommastellen; der wert ändert
sich mit der Änderung der Geschwindigkeit; die Frage ist, ob ich das nicht nach
die Berechnung und vor die Ausgabe setzen sollte

zu 3)
temp_time_secs ist ja nur die zeit zwischen dem letzten aufruf der methode und
dem jetzigen aufruf, da start_time ja am ende auf current_time gesetzt wird

zu 4)
x_double kommt aus dem sensorlistener. x_double ist nur als globale variable
definiert, damit ich sie auch in TimeDistanceRule sehen kann. x_double wird
bei jedem OnSensorChange aktualisiert

zu 5)
ja, das werd ich jetzt mal versuchen! :)

Danke schon mal
 
und wieder bin ich beim ergebnis NaN...und ich weiß einfach nicht, warum! vor allem Geschwindigkeit (aber auch velocityChange) scheinen probleme zu machen!

dabei sind beide zu jeder zeit initialisiert...auch immer korrekt als double und mindestens mit 0.0!


Edit: mir ist noch was aufgefallen: wenn ich jetzt temp_accel_value immer als die wurzel der quadradtsumme nehme kann die beschleunigung ja niemals negative werte einnehmen -> meine geschwindigkeit wird hier im
programm ständig höher, auch wenn ich langsamer laufe oder sogar stehen bleibe

frank im kampf gegen die vektoren ist noch nicht vorbei! ;)
 
Zuletzt bearbeitet:
Das start_time=current_time hab ich übersehen.
Zu deinem Edit: Da hast du recht...irgendwas fällt uns da aber auch noch ein ;)
Erst mal muss das NaN weg ;)
Bist du dir sicher das das nicht durch diese Formatierung kommt?
Übrigens solltest du die auch vor dem Thread machen können, wenn sich das eh dynamisch mitändert. Dann müssen die 5 Zeilen Code nicht jedesmal ausgeführt werden ;)
Kannst du das nochmal ohne Formatierung versuchen und deinen aktuellen Code posten?
 
hallo Felix,

ich hänge gerade gedanklich an der integralrechnung:

wenn ich v = a * t nach t integriere über ein integral von 0 bis n, dann ist dass doch die rechnung: a_tn * t_n + a_tn-1 * t_n-1 + a_tn-2 + t_n-2 + ... + a_t0 * t_0, oder?

die beschleunigung wenn ich laufe ist vergleichbar einer sinus-kurve; die negativen anteile der kurve haben wir durch die quadratwurzeln an der x-achse gespiegelt;

das entspricht auch ungefähr dem menschlichen gang: zwischen jedem schritt bremst
unser körper kurz ab.

damit ist aber wenn wir jetzt die geschwindigkeit für den zeitabschnitt ta bis tb betrachten ja einfach nur v_tb = a_tb * (tb-ta) und die darin zurück gelegte strecke
s_tb = v_tb * (tb-ta)....die gesamtgeschwindigkeit = v_0 + v_t1 + ... + v_ta + v_tb
die gesamtstrecke dann analog s_0 + s_1 + ... + s_ta + s_tb

bin ich mal soweit richtig mit meiner analysis, oder ist da schon der wurm drin?
 
Hier der derzeitige Code...leider nicht mehr so schön kommentiert! ;)

ich stell gerade fest, dass mein temp_accel_value sich sehr langsam aktualisiert (zumindest im toast) und mit diesem code geschwindigkeit und
strecke negative werden und sich geschwindigkeit sehr schnell hoch addiert!

Code:
    private Runnable TimeDistanceRule = new Runnable() {
         public void run() {
            x_calib = x_double + cx;
            y_calib = y_double + cy;
            z_calib = z_double + cz;
            current_time = System.currentTimeMillis();
            temp_time = current_time - start_time;
            temp_time_secs = (double) (temp_time) / 1000;
            
            // Low-Level Low-Pass Filter zur Vermeidung von Messungenauigkeiten
            if (x_calib < 0.05 && x_calib > -0.05){
                x_calib = 0.0;
            }
            if (y_calib < 0.05 && y_calib > -0.05){
                y_calib = 0.0;
            }
            if (z_calib < 9.85665 && z_calib > 9.75665){
                z_calib = 9.80665; // vector_sum sollte G = 9.80665 ergeben
            }
            
            // Berechnung des Bewegungsvektors
            vector_sum = Math.sqrt(Math.pow(x_calib, 2.0) + Math.pow(y_calib,2.0) + Math.pow(z_calib,2.0));
            temp_accel_value = vector_sum - SensorManager.GRAVITY_EARTH;
            
            Toast.makeText(getApplicationContext(), "temp_accel_old = " + temp_accel_old + "\ntemp_accel_value = " + temp_accel_value, Toast.LENGTH_SHORT).show();
            
            Geschwindigkeit += temp_accel_value * temp_time_secs;
            Strecke += Geschwindigkeit * temp_time_secs;
            
            start_time = current_time;
            
            NumberFormat nf = NumberFormat.getNumberInstance();
            nf.setMinimumFractionDigits(2);
            nf.setMaximumFractionDigits(3);
            formatted_v = nf.format(Geschwindigkeit);
            formatted_d = nf.format(Strecke);
            
            yVelocity.setText(getString(R.string.velocity) + ": " + formatted_v + " m/s");
            yDistance.setText(getString(R.string.distance) + ": " + formatted_d + " m");
            VecSum.setText(getString(R.string.vector) + ": " + vector_sum);
            
            TempTime.setText(getString(R.string.time) + ": " + temp_time_secs + " s");
            SensorCalibration.setText(getString(R.string.calibration) + String.format(": %+2.5f | %+2.5f | %+2.5f", cx, cy, cz));
                
            mHandler.postDelayed(this, 100);
         }
    };
 
Ich meine die Toasts kommen mit Verzögerung. Kann also gut sein, dass die Geschwindigkeit intern stimmt. Das mit dem positiv/negativ müssen wir allerdings noch bändigen...
Sind denn die NaNs weg?
 
die NaNs sind grad weg, aber die ergebnisse eher quatsch....leider
 

Ähnliche Themen

K
Antworten
1
Aufrufe
1.935
vetzki
vetzki
T
  • tanzverfuehrung
Antworten
0
Aufrufe
985
tanzverfuehrung
T
P
  • Peter123
Antworten
2
Aufrufe
3.293
hadez
H
Zurück
Oben Unten