googlearchive / tango-examples-java

Example projects for Project Tango [deprecated] Java API
https://developers.google.com/ar
503 stars 300 forks source link

toString() method in TangoPoseData class throw ArrayIndexOutOfBounds #67

Open gianmaria opened 8 years ago

gianmaria commented 8 years ago

if i call pose.toString() in the example Motion Tracking Activity, in the method:

 protected void onRender(long ellapsedRealtime, double deltaTime))

of the class:

MotionTrackingRajawaliRenderer()

it thorws:

05-30 12:00:43.132 21775-21824/com.projecttango.experiments.javamotiontracking E/AndroidRuntime: FATAL EXCEPTION: GLThread 1267 Process: com.projecttango.experiments.javamotiontracking, PID: 21775 java.lang.ArrayIndexOutOfBoundsException: length=11; index=11 at com.google.atap.tangoservice.TangoPoseData.toString(TangoPoseData.java:278) at com.projecttango.examples.java.motiontracking.MotionTrackingRajawaliRenderer.onRender(MotionTrackingRajawaliRenderer.java:108) at org.rajawali3d.renderer.RajawaliRenderer.onRenderFrame(RajawaliRenderer.java:387) at org.rajawali3d.surface.RajawaliSurfaceView$RendererDelegate.onDrawFrame(RajawaliSurfaceView.java:228) at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1523) at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

i've digged a bit and i've discovered that when the class TangoPoseData builds the string

public String toString() {
        String infoString = String.format("TangoPoseData: status: %d (%s), time: %f, base: %d (%s), target: %d (%s)\n", new Object[]{Integer.valueOf(this.statusCode), STATUS_NAMES[this.statusCode], Double.valueOf(this.timestamp), Integer.valueOf(this.baseFrame), FRAME_NAMES[this.baseFrame], Integer.valueOf(this.targetFrame), FRAME_NAMES[this.targetFrame]});
        String poseString = String.format("               p: [%.3f, %.3f, %.3f], q: [%.4f, %.4f, %.4f, %.4f]\n", new Object[]{Double.valueOf(this.translation[0]), Double.valueOf(this.translation[1]), Double.valueOf(this.translation[2]), Double.valueOf(this.rotation[0]), Double.valueOf(this.rotation[1]), Double.valueOf(this.rotation[2]), Double.valueOf(this.rotation[3])});
        return infoString + poseString;
    }

statusCode is equal to 11 and STATUS_NAMES has 11 items, this wouldn't be a big issue except that when i use Messages to communicate with the main thread and UI the method in some way gets called, i suspect, and the app crash. this is the code that i use:

public class MotionTrackingRajawaliRenderer extends RajawaliRenderer {
.....
public Message messageToSend = new Message();
    @Override
    protected void onRender(long ellapsedRealtime, double deltaTime) {
        // Update the scene objects with the latest device position and orientation information.
        // Synchronize to avoid concurrent access from the Tango callback thread below.
        try {
            TangoPoseData pose =
                TangoSupport.getPoseAtTime(0.0, TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
                                     TangoPoseData.COORDINATE_FRAME_DEVICE,
                                     TangoSupport.TANGO_SUPPORT_ENGINE_OPENGL,
                                     mCurrentScreenRotation);
            if (pose.statusCode == TangoPoseData.POSE_VALID) {
                getCurrentCamera().setPosition((float) pose.translation[0],
                                               (float) pose.translation[1],
                                               (float) pose.translation[2]);

                Quaternion invOrientation = new Quaternion((float) pose.rotation[3],
                                                            (float) pose.rotation[0],
                                                            (float) pose.rotation[1],
                                                            (float) pose.rotation[2]);

                // For some reason, rajawalli's orientation is inversed.
                Quaternion orientation = invOrientation.inverse();
                getCurrentCamera().setOrientation(orientation);

                // here i send the pose, that is valid
                messageToSend.obj = pose;
                mta.handler.sendMessage(messageToSend);
            }
        } catch (TangoErrorException e) {
            Log.e(TAG, "TangoSupport.getPoseAtTime error", e);
        }

        // Perform the actual OpenGL rendering of the updated objects
        super.onRender(ellapsedRealtime, deltaTime);
    }
}

public class MotionTrackingActivity extends Activity {
......

   public TextView textViewRawTangoData;
    public Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_motion_tracking);

        mRenderer = setupGLViewAndRenderer();

        textViewRawTangoData = (TextView) findViewById(R.id.textViewRawTangoData);

        handler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                TangoPoseData pose = (TangoPoseData) msg.obj;
                if (pose == null) return;
                String txt = customPoseToString(pose);
                if (txt == null) return;
                textViewRawTangoData.setTextColor(Color.RED);
                textViewRawTangoData.setText(txt);
            }
        };

        // Check the current screen rotation and set it to the renderer.
        WindowManager mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        Display mDisplay = mWindowManager.getDefaultDisplay();
        mRenderer.setCurrentScreenRotation(mDisplay.getOrientation());
    }

    public String customPoseToString(TangoPoseData pose) {
        int statusCode = pose.statusCode;
        String statusName = pose.STATUS_NAMES[pose.statusCode];
        double timestamp = pose.timestamp;

        int baseFrame = pose.baseFrame;
        String stringBaseFrame;
        if (baseFrame < pose.FRAME_NAMES.length)
            stringBaseFrame = pose.FRAME_NAMES[baseFrame];
        else
            stringBaseFrame = "NULL";

        String stringTargetFrame;
        int targetFrame = pose.targetFrame;
        if (targetFrame < pose.FRAME_NAMES.length)
            stringTargetFrame = pose.FRAME_NAMES[targetFrame];
        else
            stringTargetFrame = "NULL_2";

        String infoString = String.format("TangoPoseData: status: %d (%s), time: %f, base: %d (%s), target: %d (%s)\n",
                statusCode, statusName, timestamp, baseFrame, stringBaseFrame, targetFrame, stringTargetFrame);

        String poseString = String.format("               p: [%.3f, %.3f, %.3f], q: [%.4f, %.4f, %.4f, %.4f]\n",
                pose.translation[0], pose.translation[1], pose.translation[2],
                pose.rotation[0], pose.rotation[1], pose.rotation[2], pose.rotation[3]);

        return infoString + poseString;
    }
}