Linear Acceleration With Android API v2

This discussion was created from comments split from: SensorFusion problem.

Comments

  • Hi Eric,

    I'm trying to do something similar. 

    I'm using your data collection at the bottom of: https://mbientlab.com/androiddocs/2.7.0/sensor_fusion.html 

    But instead of quaternion I want to use linear acceleration. Can you please tell me what changes do I need to make to do that? I'm using version 2.7.0
  • Change "quaternion" to "linear acceleration" and update the value casts to the appropriate type listed in the 3rd data.  Relevant APi documentation linked below.

    https://mbientlab.com/docs/metawear/android/2/com/mbientlab/metawear/module/SensorFusion.SourceSelector.html
  • edited March 2017
    What should I replace SensorFusion.Quaternion.class with:
    Log.i("SensorFusion data:", msg.getData(SensorFusion.Quaternion.class).toString());
    I'm using IMUPlus: sensorFusion.configure()
    .setMode(SensorFusion.Mode.IMU_PLUS)
    .setAccRange(SensorFusion.AccRange.AR_8G)
    .setGyroRange(SensorFusion.GyroRange.GR_1000DPS)
    .commit();

    SensorFusion.java:

    public interface SensorFusion extends MetaWearBoard.Module {

    enum AccRange {
    AR_2G, AR_4G, AR_8G, AR_16G, }

    enum GyroRange {
    GR_2000DPS, GR_1000DPS, GR_500DPS, GR_250DPS }

    enum CalibrationAccuracy {
    UNRELIABLE, LOW_ACCURACY, MEDIUM_ACCURACY, HIGH_ACCURACY }

    enum Mode {
    SLEEP, NDOF, IMU_PLUS, COMPASS, M4G }

    enum DataOutput {
    CORRECTED_ACC, CORRECTED_GYRO, CORRECTED_MAG, QUATERNION, EULER_ANGLES, GRAVITY_VECTOR, LINEAR_ACC }

    interface CorrectedCartesianFloat {
    float x(); float y(); float z();
    CalibrationAccuracy accuracy(); }

    interface EulerAngle {
    float heading(); float pitch(); float yaw(); float roll();
    }

    interface Quaternion {
    float w(); float x(); float y(); float z();
    }

    interface SourceSelector {
    DataSignal fromCorrectedAcc();
    DataSignal fromCorrectedGyro();
    DataSignal fromCorrectedMag();
    DataSignal fromGravity();
    DataSignal fromEulerAngles();
    DataSignal fromQuaternions();
    DataSignal fromLinearAcceleration();
    }

    interface ConfigEditor {
    ConfigEditor setMode(Mode mode);
    ConfigEditor setAccRange(AccRange range);
    ConfigEditor setGyroRange(GyroRange range);
    void commit();
    }

    SourceSelector routeData();
    ConfigEditor configure();

    void start(DataOutput ... output);
    void stop();
    }
  • edited March 2017
    That link says that I need to use "CartesianFloat". But in your SensorFusion.java, there is no "CartesianFloat". There is the this comment above interface CorrectedCartesianFloat {...}:
    /**
    * Variant of the {@link com.mbientlab.metawear.data.CartesianFloat CartesianFloat} type that includes
    * the calibration accuracy of the data
    * @author Eric Tsai
    */ 
    interface CorrectedCartesianFloat {
    float x();
    float y();
    float z();
    CalibrationAccuracy accuracy();
    }
    But when I use msg.getData(SensorFusion.CorrectedCartesianFloat.class) I get the following error repeatedly while running the app:
    E/MetaWear: Background task reported an error
                java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException: Type 'interface com.mbientlab.metawear.module.SensorFusion$CorrectedCartesianFloat' not supported for message class: class com.mbientlab.metawear.data.SensorFusionCartesianFloatMessage
                    at java.util.concurrent.FutureTask.report(FutureTask.java:94)
                    at java.util.concurrent.FutureTask.get(FutureTask.java:164)
                    at com.mbientlab.metawear.MetaWearBleService$3.run(MetaWearBleService.java:1345)
                    at java.util.TimerThread.mainLoop(Timer.java:555)
                    at java.util.TimerThread.run(Timer.java:505)
                 Caused by: java.lang.UnsupportedOperationException: Type 'interface com.mbientlab.metawear.module.SensorFusion$CorrectedCartesianFloat' not supported for message class: class com.mbientlab.metawear.data.SensorFusionCartesianFloatMessage
                    at com.mbientlab.metawear.data.SensorFusionCartesianFloatMessage.getData(SensorFusionCartesianFloatMessage.java:74)
                    at com.mbientlab.metawear.callaghaninnovationapp.DeviceSetupActivityFragment$1$4$1.process(DeviceSetupActivityFragment.java:248)
                    at com.mbientlab.metawear.impl.DefaultMetaWearBoard$70.run(DefaultMetaWearBoard.java:4510)
                    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
                    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                    at java.lang.Thread.run(Thread.java:761)
  • edited March 2017
    OK, so I changed Log.i("example", msg.getData(SensorFusion.Quaternion.class).toString()); to Log.i("SensorFusion data:", msg.getData(CartesianFloat.class).toString()); and I don't get that error anymore. However, now I'm facing another problem. I have an app where I press a single button and write the data from the accelerometer, gyroscope, magnetometer and sensor fusion to files saved on my mobile device. I first implemented the accelerometer, gyroscope, and magnetometer and my app was saving the data alright. But, now that I've implemented the SensorFusion, as described above, the total amount of magnetometer data saved ends up being substantially lower than accelerometer and gyroscope. For instance, when the file size of accelerometer and gyroscope is around 100 kb, magnetometer file is around 20 kb. When I comment out the SensorFusion code, the file sizes are comparable. Why is this happening and how can I fix this?
  • edited March 2017
    The other problem I'm facing with SensorFusion is that the bluetooth drops connection after just a few seconds. Below is the error I get. Again, this does not happen when I comment out the sensorfusion implementation code.

    V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@cbb186
    V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@a759a47
    V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@e216012
    V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@f6793e3
    D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=8 device=C5:2C:1E:F6:FD:DD
    D/BluetoothGatt: refresh() - device: C5:2C:1E:F6:FD:DD
    D/BluetoothGatt: close()
    D/BluetoothGatt: unregisterApp() - mClientIf=8
    D/BluetoothGatt: connect() - device: C5:2C:1E:F6:FD:DD, auto: false
    D/BluetoothGatt: registerApp()
    D/BluetoothGatt: registerApp() - UUID=a1380330-28e5-4a09-99af-df587bc42d2c
    D/BluetoothGatt: onClientRegistered() - status=0 clientIf=8
    V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@458040f
    V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@d507c9c
    V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@78d0a7a
    V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@49ad22b
    I/art: Do full code cache collection, code=483KB, data=422KB
    I/art: After code cache collection, code=450KB, data=367KB
    D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=8 device=C5:2C:1E:F6:FD:DD
    D/BluetoothGatt: discoverServices() - device: C5:2C:1E:F6:FD:DD
    D/BluetoothGatt: onSearchComplete() = Device=C5:2C:1E:F6:FD:DD Status=0
    D/BluetoothGatt: setCharacteristicNotification() - uuid: 00002a19-0000-1000-8000-00805f9b34fb enable: true
    D/BluetoothGatt: setCharacteristicNotification() - uuid: 326a9006-85cb-9195-d9dd-464cfbbae75a enable: true
    W/BluetoothGatt: onCharacteristicRead() - Device=C5:2C:1E:F6:FD:DD handle=26 Status=0
  • You can't stream that much data at once; either stream acc + gyro + mag data or stream one sensor fusion output.  Furthermore, you'll also want to configure the ble connection to handle high frequency streaming and use the high frequency data signals for acc, gyro, and mag.

    This section explains what you need to do for APi v3 but you can implement the same setup with API v2.
  • OK, I removed sensor fusion and am only saving the 9 axis acc, gyro and mag data. The bluetooth connection got better but it still disconnects after about 40 minutes, and does not reconnect on its own (keeps showing the "reconnecting.." window). I need to collect this data continuously for 8 hours.

    That code you pointed to for improving the bluetooth connection is not working for version 2.7.0. I searched and found the following for acc and gyro:

    https://mbientlab.com/androiddocs/2.7.0/bmi160_gyro.html#high-frequency-streaming

    But I can't find one for magnetometer. Can you show me the code for that one? 


  • edited March 2017
    • What Android device and OS are you running?
    • What does your code look like so far?
    • Is the board simply running out of power?
      • If not, what are the status codes / log messages returned from the BluetoothGatt operations?

    The DataSignal for high frequency magnetic field data is returned by fromHighFreqBField.  

  • I'm using Samsung galaxy tab 2 with Android version 6.0.1.

    When I run acc+gyro+mag all together, as in the code below, the data is not saved and displayed in real time. There is a time lag. But when I comment out any two and run only one of them, then the data is streamed real time. Why is that and how can I fix it? I will do the bluetooth test again and send you the log in another message.

    I'm unable to post my code here due to the character limit. Is there any other way I could send you my code?
  • Post it on pastebin
  • You still need to reduce the max connection interval as described in the documentation I linked.  Furthermore, you can't stream multiple sensors at 200Hz; reduce those streams to 100Hz and then you can add in the magnetometer.
This discussion has been closed.