Accelerometer issues

Hey guy,



I have an issue with the accelerometer from Android. I do know that you guys aren’t supposed to deal with that kind of troubles but maybe you could help me with this.



I create a platform and I’d like this platform to roll/pitch/yaw according to the accelerometer updates. So here is a simple code:



[java]import java.util.logging.Logger;

import android.app.Activity;

import android.hardware.Sensor;

import android.hardware.SensorEvent;

import android.hardware.SensorEventListener;

import android.hardware.SensorManager;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.collision.shapes.BoxCollisionShape;

import com.jme3.bullet.collision.shapes.SphereCollisionShape;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.input.android.AndroidInput;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.FastMath;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Sphere;

import com.lesmobilizers.tehmoballizer.general.AndroidApplication;

public class Test1 extends AndroidApplication {

private final static Logger logger = Logger.getLogger(Test1.class.getName());

private BulletAppState bulletAppState;

private float ratio;

private Activity activity;

private Node platformNode;

public Test1() {

super();

}

public Test1(Activity activity, AndroidInput input) {

super(activity, input);

}

@Override

public void init() {

SensorManager mSensorManager = (SensorManager) super.getActivity().getSystemService(super.getActivity().SENSOR_SERVICE);

mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL);

ratio = 0.5f;

bulletAppState = new BulletAppState();

logger.info("CHECK: application’s physical state creation… DONE");

stateManager.attach(bulletAppState);

logger.info("CHECK: physical state’s binding to state manager… DONE");

logger.info("CHECK: physical space’s enablement… DONE");

initCamera(ratio20);

initPlatform();

initBall();

}

public void update(float tpf){

logger.info("CHECK: update… DONE");

// platformNode.rotate(0, 0, FastMath.PI/12
FastMath.sin(tpf));

}

private void initPlatform(){

Box platform = new Box(ratio * 10, ratio * 2, ratio * 10);

logger.info("CHECK: platform’s box creation… DONE");

Geometry platformGeometry = new Geometry("platform", platform);

logger.info("CHECK: platform’s geometry creation… DONE");

Material platformMaterial = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");

logger.info("CHECK: platform’s material creation… DONE");

platformMaterial.setColor("m_Color", ColorRGBA.Red);

logger.info("CHECK: platform’s color setup… DONE");

platformGeometry.setMaterial(platformMaterial);

logger.info("CHECK: platform’s material setup… DONE");

platformGeometry.setLocalTranslation(new Vector3f(0, -3f, 0));

logger.info("CHECK: platform’s geometry translation… DONE");

// platformGeometry.rotate(0, 0, FastMath.PI/6);

// logger.info("CHECK: platform’s geometry rotation… DONE");

BoxCollisionShape platformCollisionShape = new BoxCollisionShape(new Vector3f(ratio * 10, ratio * 2, ratio * 10));

logger.info("CHECK: platform’s collision shape creation… DONE");

RigidBodyControl platformPhysics = new RigidBodyControl(platformCollisionShape, 0f);

logger.info("CHECK: platform’s body controls creation… DONE");

platformGeometry.addControl(platformPhysics);

logger.info("CHECK: platform’s body controls adding… DONE");

platformPhysics.setKinematic(true);

logger.info("CHECK: platform’s kinematic mode enablement… DONE");

bulletAppState.getPhysicsSpace().add(platformPhysics);

logger.info("CHECK: platform adding to the physics space… DONE");

platformNode = new Node("platformNode");

logger.info("CHECK: platform’s node creation… DONE");

platformNode.attachChild(platformGeometry);

logger.info("CHECK: platform’s attachment to the node… DONE");

rootNode.attachChild(platformNode);

logger.info("CHECK: platform’s node attachment to the root node… DONE");

}

private void initBall(){

Sphere ball = new Sphere(100, 100, 1ratio, true, false);

logger.info("CHECK : creating ball spatial… DONE");

Geometry ballGeometry = new Geometry("Ball", ball);

logger.info("CHECK : creating geometry… DONE");

Material ballMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

logger.info("CHECK : creating material… DONE");

ballMaterial.setColor("Color", ColorRGBA.Blue);

logger.info("CHECK : setting material color… DONE");

ballGeometry.setMaterial(ballMaterial);

logger.info("CHECK : applying material… DONE");

ballGeometry.setLocalTranslation(new Vector3f(0, 5f, 0));

logger.info("CHECK : translating spatial… DONE");

SphereCollisionShape ballCollisionShape = new SphereCollisionShape(1
ratio);

logger.info("CHECK: ball’s collision shape creation… DONE");

RigidBodyControl ballPhysics = new RigidBodyControl(ballCollisionShape, 1f);

logger.info("CHECK: ball’s body controls creation… DONE");

ballGeometry.addControl(ballPhysics);

logger.info("CHECK: ball’s body controls adding… DONE");

bulletAppState.getPhysicsSpace().add(ballPhysics);

logger.info("CHECK: ball adding to the physics space… DONE");

rootNode.attachChild(ballGeometry);

logger.info("CHECK : attaching geometry to node… DONE");

}

private void initCamera(float distance) {

cam.setLocation(new Vector3f(0, 0.866fdistance, 0.5fdistance));

logger.info("CHECK: camera’s location setup… DONE");

cam.lookAt(Vector3f.ZERO, new Vector3f(0, 1, 0));

logger.info("CHECK: camera’s ‘lookAt’ direction setup… DONE");

cam.setFrustumFar(100);

logger.info("CHECK: camera’s frustum setup… DONE");

}

private final SensorEventListener mSensorListener = new SensorEventListener() {

public void onSensorChanged(SensorEvent se) {

float x = se.values[0];

float y = se.values[1];

float z = se.values[2];

platformNode.rotate(x, y, z);

}

public void onAccuracyChanged(Sensor sensor, int accuracy) {

}

};

}[/java]



I read to some tutorials for the accelerometer part but when I run this code my app crashes with the error:


java.lang.IllegalStateException: Scene graph is not properly updated for rendering


I provide my log too:

...
05-19 11:59:09.183: INFO/Test1(6839): CHECK: application's physical state creation... DONE
05-19 11:59:09.255: DEBUG/dalvikvm(6839): GC_FOR_MALLOC freed 4733 objects / 283168 bytes in 44ms
05-19 11:59:09.276: INFO/Test1(6839): CHECK: physical state's binding to state manager... DONE
05-19 11:59:09.276: INFO/Test1(6839): CHECK: physical space's enablement... DONE
05-19 11:59:09.276: INFO/Test1(6839): CHECK: camera's location setup... DONE
05-19 11:59:09.276: INFO/Test1(6839): CHECK: camera's 'lookAt' direction setup... DONE
05-19 11:59:09.276: INFO/Test1(6839): CHECK: camera's frustum setup... DONE
05-19 11:59:09.276: INFO/Test1(6839): CHECK: platform's box creation... DONE
05-19 11:59:09.276: INFO/Test1(6839): CHECK: platform's geometry creation... DONE
05-19 11:59:09.276: INFO/MaterialDef(6839): 19 May 2011 11:59:09 com.jme3.material.MaterialDef
05-19 11:59:09.276: INFO/MaterialDef(6839): INFO: Loaded material definition: Solid Color
05-19 11:59:09.313: INFO/Test1(6839): CHECK: platform's material creation... DONE
05-19 11:59:09.313: WARN/Material(6839): 19 May 2011 11:59:09 com.jme3.material.Material checkSetParam
05-19 11:59:09.313: WARN/Material(6839): WARNING: Material parameter m_Color uses a deprecated naming convention use Color instead
05-19 11:59:09.313: INFO/Test1(6839): CHECK: platform's color setup... DONE
05-19 11:59:09.313: INFO/Test1(6839): CHECK: platform's material setup... DONE
05-19 11:59:09.313: INFO/Test1(6839): CHECK: platform's geometry translation... DONE
05-19 11:59:09.313: INFO/Test1(6839): CHECK: platform's collision shape creation... DONE
05-19 11:59:09.313: INFO/Test1(6839): CHECK: platform's body controls creation... DONE
05-19 11:59:09.313: INFO/Test1(6839): CHECK: platform's body controls adding... DONE
05-19 11:59:09.313: INFO/Test1(6839): CHECK: platform's kinematic mode enablement... DONE
05-19 11:59:09.313: INFO/PhysicsSpace(6839): 19 May 2011 11:59:09 com.jme3.bullet.PhysicsSpace addRigidBody
05-19 11:59:09.313: INFO/PhysicsSpace(6839): INFO: Adding RigidBody com.bulletphysics.dynamics.RigidBody@46d592e8 to physics space.
05-19 11:59:09.323: INFO/Test1(6839): CHECK: platform adding to the physics space... DONE
05-19 11:59:09.323: INFO/Test1(6839): CHECK: platform's node creation... DONE
05-19 11:59:09.323: INFO/com.jme3.scene.Node(6839): 19 May 2011 11:59:09 com.jme3.scene.Node attachChild
05-19 11:59:09.323: INFO/com.jme3.scene.Node(6839): INFO: Child (platform) attached to this node (platformNode)
05-19 11:59:09.323: INFO/Test1(6839): CHECK: platform's attachment to the node... DONE
05-19 11:59:09.323: INFO/com.jme3.scene.Node(6839): 19 May 2011 11:59:09 com.jme3.scene.Node attachChild
05-19 11:59:09.323: INFO/com.jme3.scene.Node(6839): INFO: Child (platformNode) attached to this node (Root Node)
05-19 11:59:09.323: INFO/Test1(6839): CHECK: platform's node attachment to the root node... DONE
05-19 11:59:09.353: DEBUG/dalvikvm(6839): GC_EXTERNAL_ALLOC freed 2722 objects / 168040 bytes in 27ms
05-19 11:59:09.793: INFO/Test1(6839): CHECK : creating ball spatial... DONE
05-19 11:59:09.793: INFO/Test1(6839): CHECK : creating geometry... DONE
05-19 11:59:09.793: INFO/Test1(6839): CHECK : creating material... DONE
05-19 11:59:09.793: INFO/Test1(6839): CHECK : setting material color... DONE
05-19 11:59:09.793: INFO/Test1(6839): CHECK : applying material... DONE
05-19 11:59:09.793: INFO/Test1(6839): CHECK : translating spatial... DONE
05-19 11:59:09.793: INFO/Test1(6839): CHECK: ball's collision shape creation... DONE
05-19 11:59:09.793: INFO/Test1(6839): CHECK: ball's body controls creation... DONE
05-19 11:59:09.793: INFO/Test1(6839): CHECK: ball's body controls adding... DONE
05-19 11:59:09.803: INFO/PhysicsSpace(6839): 19 May 2011 11:59:09 com.jme3.bullet.PhysicsSpace addRigidBody
05-19 11:59:09.803: INFO/PhysicsSpace(6839): INFO: Adding RigidBody com.bulletphysics.dynamics.RigidBody@46ce26c8 to physics space.
05-19 11:59:09.803: INFO/Test1(6839): CHECK: ball adding to the physics space... DONE
05-19 11:59:09.803: INFO/com.jme3.scene.Node(6839): 19 May 2011 11:59:09 com.jme3.scene.Node attachChild
05-19 11:59:09.803: INFO/com.jme3.scene.Node(6839): INFO: Child (Ball) attached to this node (Root Node)
05-19 11:59:09.803: INFO/Test1(6839): CHECK : attaching geometry to node... DONE
05-19 11:59:09.803: INFO/Test1(6839): CHECK: update... DONE
05-19 11:59:09.823: WARN/OGLESShaderRenderer(6839): glError 1280
05-19 11:59:09.833: INFO/global(6839): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
05-19 11:59:09.843: INFO/global(6839): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
05-19 11:59:09.893: WARN/OGLESShaderRenderer(6839): glError 1280
05-19 11:59:09.923: INFO/Test1(6839): CHECK: update... DONE
05-19 11:59:09.923: DEBUG/lifecycle(1312): onStop:com.lge.launcher.Launcher@46cc5588
05-19 11:59:09.923: INFO/INKSPOT(1312): ContentResolver.unregisterContentObserver : android.database.AbstractCursor$SelfContentObserver@46c37bc0
05-19 11:59:09.933: INFO/INKSPOT(1312): ContentResolver.unregisterContentObserver : android.database.AbstractCursor$SelfContentObserver@46bfbb90
05-19 11:59:09.933: INFO/INKSPOT(1312): ContentResolver.unregisterContentObserver : android.database.AbstractCursor$SelfContentObserver@46db9b10
05-19 11:59:09.933: INFO/INKSPOT(1312): ContentResolver.unregisterContentObserver : android.database.AbstractCursor$SelfContentObserver@46d49db0
05-19 11:59:09.985: WARN/dalvikvm(6839): threadid=8: thread exiting with uncaught exception (group=0x40020ce0)


Thx for help !

My wild guess would be, that the listener is called after the update for the rendering is done, and this couses the problem. If you disable the rotation/ add a manual updateGeometricState behind it, does it work then?

Nice hit :wink:



Well do you see any mean to make the update happen after the listener is being called ? 'cause not using the update method in the listener is a pretty ulgy way to code this… I mean it works but it’s really not conventional.

I think you’re supposed to use the new AndroidTouchInputListener?

I thought it was only handling touch events and not motion ones but would you have some code example so I get started with this listener ?

I see.

OK, we’ll probably need that one as well.



As a short-term solution to your problem, you can set some value like:

[java]

Vector3f vec = new Vector3f();

// …

// sensor event

vec.set(x,y,z);

[/java]



Then in your simpleUpdate() method you can do the rotation:

[java]platformNode.rotate(vec);[/java]

Yeah that’s pretty similar to what I did. But I have another issue with this (2 actually).



First, it seems to make the platform moving with lot of small saccades instead of moving analogically. You can’t see it with eyes but when i put a ball on it, the ball has strange moves (like small jumps again and agin) as soon as I move the platform.



Then (and I think this is linked to the rotate method), there is a shift of the platform along the moves. I mean, let’s imagine that i start running the app with a zero angle. then I turn the phone around some axis with an angle of 60° for example. And finally, I put the phone back into the start position. The platform is supposed to be back in it’s initial position too but it’s not the case. It’s shifted with a certain angle which is pretty consequent. And I don’t know where it comes from.

The AndroidInput handles touch screen inputs and gestures, but currently no accelerator sensor events.

But its a good idea to include it there.

The onSensorChanged event comes in as a different android thread, so you are not inside the GLThread, which

is problematic.

AndroidInput handles this by transfering the events and calling your code from the GLThread.

How to use it:

AndroidInput.setInputListener(class implementing AndroidTouchInputListener);

Callbacks:

@Override

public void onMotionEvent(MotionEvent evt)

{

if (evt.getAction() == MotionEvent.ACTION_MOVE)

{

for (pointId = 0; pointId < evt.getPointerCount(); pointId++)

{

lastX = evt.getX(pointId);

lastY = fScreenHeight - evt.getY(pointId);



@Override

public void onTouchEvent(TouchEvent evt)

{

if (evt.getType() == TouchEvent.Type.TAP)

{

lastX = evt.getX();

lastY = fScreenHeight - evt.getY();



@Override

public void onAndroidKeyEvent(KeyEvent evt)

{

if (evt.getAction() == KeyEvent.ACTION_DOWN)

{

evt.getKeyCode()