Autore Topic: Fisica di una pallina con accelerometro  (Letto 783 volte)

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Fisica di una pallina con accelerometro
« il: 15 Marzo 2012, 17:41:52 CET »
0
Ciao a tutti,
ci ho sbattuto la testa parecchio e volevo un vostro consiglio: sto sviluppando per tesi un tipico labirinto in cui si muove una pallina, comandata con l'accelerometro.

L'accelerometro restituisce l'accelerazione lungo uno degli assi, quindi in m/s2

Essendo quindi l'unità di misura spaziale in metri, o ogni misura in pixel del mio labirinto la porto in metri o cerco di portare in pixel l'accelerazione.
Ho provato, ma purtroppo la pallina è veramente troppo veloce.

Codice (Java): [Seleziona]
public void onSensorChanged(SensorEvent event) {
                float x = event.values[0];
                float y = event.values[1];

        mBall.accelX = -x * mMetersToPixelsX* 0.7f;
        mBall.accelY = y * mMetersToPixelsY*0.7f;
        }

Dove:
Codice (Java): [Seleziona]
DisplayMetrics metrics = new DisplayMetrics();
                mDisplay.getMetrics(metrics);
                mXDpi = metrics.xdpi;
        mYDpi = metrics.ydpi;
        mMetersToPixelsX = mXDpi / 0.0254f;
        mMetersToPixelsY = mYDpi / 0.0254f;
Queste 2 costanti (mMetersToPixelsX,   mMetersToPixelsY) moltiplicate per una misura in metri dovrebbero darmi quella in pixel, a seconda dei dpi del device.

Il problema è che si aggirano sui 6000. Come vedere ho provato ad aggiungere un fattore 0.7 tipo attrito, ma è veramente ancora troppo veloce. Per gli spostamenti utilizzo l'integrale di verlet:

Codice (Java): [Seleziona]
public void verletUpdateBall(){
        currT = System.nanoTime();
        dT = (currT - lastT)/1000000000f;
       
        float tempPosX = posX;
        posX += (posX - lastPosX) + accelX * dT * dT;
        lastPosX = tempPosX;
       
        float tempPosY = posY;
        posY += (posY - lastPosY) + accelY * dT * dT;
        lastPosY = tempPosY;
       
        lastT = currT;
    }

Il tutto è molto simile al sample AccelerometerPlay fornito con l'SDK.
Qualcuno è pratico e può consigliarmi? Io sinceramente vorrei poi lavorare sui pixel all'interno del labirinto in quanto più comodo.

Grazie in anticipo.

Offline pivoide

  • Utente junior
  • **
  • Post: 133
  • Respect: +19
    • Mostra profilo
  • Dispositivo Android:
    Samsung galaxy tab 10.1
  • Play Store ID:
    codicerosso
  • Sistema operativo:
    Ubuntu 11.04
Re:Fisica di una pallina con accelerometro
« Risposta #1 il: 16 Marzo 2012, 02:20:43 CET »
0
Scusa ma se usi l'integrale non dovrebbe esserci 1/2 * a*t*t?
Odio l'inglese e per un informatico non è il massimo

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Re:Fisica di una pallina con accelerometro
« Risposta #2 il: 16 Marzo 2012, 12:24:27 CET »
0
Scusa ma se usi l'integrale non dovrebbe esserci 1/2 * a*t*t?

In teoria usando il moto uniformemente accelerato si, qui però di quel coefficiente nemmeno l'ombra...

Si usa un altro approccio:
http://www.gamedev.net/page/resources/_/technical/math-and-physics/a-verlet-based-approach-for-2d-game-physics-r2714

Offline thebestneo

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
Re:Fisica di una pallina con accelerometro
« Risposta #3 il: 16 Aprile 2012, 17:35:09 CEST »
0
Ho modificato leggermente il codice e va un po' meglio, anche se il moto della pallina non è soddisfacente (poca inerzia della pallina).
Avrei bisogno che qualcuno però mi desse qualche consiglio, a partire da questa parte di codice:
Codice (Java): [Seleziona]
DisplayMetrics metrics = new DisplayMetrics();
                mDisplay.getMetrics(metrics);
                mXDpi = metrics.xdpi;
        mYDpi = metrics.ydpi;

        mMetersToPixelsX = mXDpi / 0.0254f;
        mMetersToPixelsY = mYDpi / 0.0254f;
Ottendo i due coefficienti da applicare alle mie misure in metri per ottenere i pixel. Per evitare di applicarli ovunque e mappare l'intera simulazione, avevo pensato di applicarli esclusivamente all'unico dato che ho che contiene metri, ovvero l'accelerazione:

Codice (Java): [Seleziona]
 
mBall.accelX = -x * mMetersToPixelsX;
 mBall.accelY = y * mMetersToPixelsY;

Mi chiedo però se sia corretto fare questa trasformazione che mi farebbe avere pixel/s2

Un'altra parte che vorrei mostrarvi per avere consigli è quella che gestisce il moto della pallina:

Codice (Java): [Seleziona]
currT = System.nanoTime();
        dT = (currT - lastT)/1000000000f;
        if(dT > (1f/60f)){
                dT = 1f/60f;
                //Log.d("debug", "timestep toobig");
        }
        if(lastDT != 0){
                float tempPosX = posX;
                posX += friction * (posX - lastPosX) * (dT/lastDT)+ accelX * dT * dT;
                lastPosX =  tempPosX;
               
                float tempPosY = posY;
                posY += friction * (posY -  lastPosY) * (dT/lastDT)+ accelY * dT * dT ;
                lastPosY = tempPosY;
        }
       
       
        lastDT = dT;
        lastT = currT;

(dT/lastDT) è un coefficiente per stabilizzare l'algoritmo in caso di timesteps fluttuanti, anche se ho letto (e proverò in seguito) che è meglio disaccoppiare timesteps di rendering da quelli della simulazione fisica, questi ultimi andrebbero costanti per evitare comportamenti strani.
L'algoritmo è corretto? Mi sembra che la pallina abbia appunto poca inerzia, cambia direzione troppo repentinamente.

Grazie a chiunque risponda.