Showing posts with label android-sensors. Show all posts
Showing posts with label android-sensors. Show all posts

Sunday, February 18, 2018

Android process is bad error on killing the app

Leave a Comment

Here is the exact error

02-08 12:36:43.490 3479-4980/? W/ActivityManager: Scheduling restart of crashed service com.wfl/.StepTrackerShakeDetectorService in 1000ms  02-08 12:36:44.494 3479-3513/? W/ActivityManager: Unable to launch app com.wfl/10139 for service Intent { cmp=com.wfl/.StepTrackerShakeDetectorService }: process is bad 

Here is the scenario It is basically a step tracker

StepTrackerShakeDetectorService is implemented to restart automatically when app is destroyed using START_STICKY

But when the app is removed from task list I am getting this error.

Here is the code.

public class StepTrackerShakeDetectorService extends Service {      private SensorManager mSensorManager;     private StepTrackerShakeDetector mShakeDetector;     private Sensor step_counter_sensor;     private Sensor step_detector_sensor;     private Sensor step_accelerometer;      @Override     public IBinder onBind(Intent intent) {         return null;     }      @Override     public void onCreate() {          registerDetector();     }       private void registerDetector() {          mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);          step_counter_sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);         step_detector_sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);         step_accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);          if (step_counter_sensor != null) // sensor not supported         {             mShakeDetector = new StepTrackerShakeDetector(Sensor.TYPE_STEP_COUNTER);             mSensorManager.registerListener(mShakeDetector, step_counter_sensor, SensorManager.SENSOR_DELAY_FASTEST);         } else if (step_accelerometer != null) {              mShakeDetector = new StepTrackerShakeDetector(Sensor.TYPE_ACCELEROMETER);             mSensorManager.registerListener(mShakeDetector, step_accelerometer, SensorManager.SENSOR_DELAY_FASTEST);         }           mShakeDetector.setOnShakeListener(new StepTrackerShakeDetector.OnShakeListener() {              @Override             public void onShake(int count) {               //Code to calculate steps             }         });     }      private void unregisterDetector() {         mSensorManager.unregisterListener(mShakeDetector);     }      @Override     public void onStart(Intent intent, int startId) {         super.onStart(intent, startId);     }      @Override     public int onStartCommand(Intent intent, int flags, int startId) {         return START_STICKY;     }      @Override     public void onDestroy() {         unregisterDetector();         super.onDestroy();     }      @Override     public void onTaskRemoved(Intent rootIntent) {         super.onTaskRemoved(rootIntent);         Intent intent = new Intent(getApplicationContext(), StepTrackerShakeDetectorService.class);         PendingIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);         AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);         alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 2000, pendingIntent);     }   } 

Here is the error in lenovo phab 2

02-13 11:42:12.211 975-1964/? W/ActivityManager: Scheduling restart of crashed service com.wfl/.StepTrackerShakeDetectorService in 1000ms 02-13 11:42:12.213 975-1964/? I/ActivityManager:   Force stopping service ServiceRecord{7a45ff2 u0 com.wfl/.StepTrackerShakeDetectorService} 02-13 11:42:12.214 975-1964/? V/ActivityManager: Broadcast: Intent { act=android.intent.action.PACKAGE_RESTARTED dat=package:com.wfl flg=0x10 (has extras) } ordered=false userid=0 callerApp=null 02-13 11:42:12.216 975-2003/? W/ActivityManager: Spurious death for ProcessRecord{2325a63 0:com.wfl/u0a146}, curProc for 30626: null 02-13 11:42:12.790 2342-2361/? D/GasService: FG app changed: from com.wfl to  

2 Answers

Answers 1

Put this line at the end of the function in onTaskRemoved

        super.onTaskRemoved(rootIntent); 

Answers 2

Change your onbind method which returns null to

@Override public IBinder onBind(Intent intent) {     return new Binder(); } 

and run again if not working please see the below links

Why does my Android service get restarted when the process is killed, even though I used START_NOT_STICKY?

In the below link, one is using the same procedure to get alarm services and the others services in back ground check this out also

Service crashing and restarting

Read More

Saturday, June 24, 2017

Compass - Track number of full 360 degree rotations

Leave a Comment

Suppose a person is using this compass, and beginning from 90 degrees they start rotating either clockwise or counterclockwise. What's the best way to keep count of how many full 360 degree rotations they complete? Assuming they'll be rotating either only clockwise or only counterclockwise from beginning to end.

I kept coming up with solutions where if the beginning bearing is, for example, 90 degrees I keep checking the next bearing when the sensor data changes, and if it's consistently moving in one direction I know they're rotating. And if they keep rotating in that direction and make it back to 90 degrees, that counts as one rotation. My way seems very convoluted and inefficient and I'm having a hard time coming up with a better way.

In this scenario, I'd be expecting multiple full rotations.

I'd appreciate any help. Thank you!

I found this related answer and am trying to put together a code sample for that. If someone has already done something similar, please post it!

@Override public void onSensorChanged(SensorEvent event) {     switch(event.sensor.getType())     {         case Sensor.TYPE_GRAVITY:         {             mValuesAccelerometer = lowPass(event.values.clone(), mValuesAccelerometer);             break;         }         case Sensor.TYPE_MAGNETIC_FIELD:         {             mValuesMagneticField = lowPass(event.values.clone(), mValuesMagneticField);             break;         }     }      boolean success = SensorManager.getRotationMatrix(             mMatrixR,             mMatrixI,             mValuesAccelerometer,             mValuesMagneticField);      if (success)     {         SensorManager.getOrientation(mMatrixR, mMatrixValues);          float azimuth = toDegrees(mMatrixValues[0]);         float pitch = toDegrees(mMatrixValues[1]);         float roll = toDegrees(mMatrixValues[2]);          if (azimuth < 0.0d)         {             //The bearing in degrees             azimuth += 360.0d;         }     } } 

4 Answers

Answers 1

If you're sure that they'll be moving in only 1 direction, to optimize your code you can have checkpoints for degrees instead of continuously monitoring if they're still moving in the right direction.

Here's a rough algo to do that

//You noted 90 degree as starting point // checkpoint 1 will be 180 keep it as a boolean  // now you've reached 180 if the meter gets to 180 before going to next checkpoint  // which is 270 then make 180 false. it means they turned back.  // if they make it to 270 then wait for 0 degrees and do the same.  // if they make it back to 90 like that. You got a rotation and hopefully  // a bit of complexity is reduced as you're just checking for 4 checkpoints  

I don't have any code handy at the moment.

Answers 2

Create 3 integers

int rotationCount=0 int currentDegrees=0 int previousDegrees=89 

not a java programmer so i dont know how you handle the onSensorChanged event but basically perform a check within a while loop

while (currentDegrees + 90 < 360) {     if (currentDegrees + 90 == 0)      {         if (previousDegrees == 359)          {             rotationCount = rotationCount + 1         }     }     else if (currentDegrees + 90 == 359)      {         if (previousDegrees == 0)          {             rotationCount = rotationCount - 1         }       }     previousDegrees = currentDegrees + 90 } 

sorry about the syntax, this is just an example of how to do so..

Answers 3

This is a tracking problem with a reading that overflows. You need to keep track of the last reading and hope the user doesn't do more than a half turn between each reading.... (because of the Nyquist theorem)

Here is the basic pseudo code.

var totalChange = 0; var lastAzimuth = -1000;  function CountTurns(az) {   if (az > 180) az -= 360;   // do this if your azimuth is always positive i.e. 0-360.    if (lastAzimuth == -1000)   {     lastAzimuth = az;   }    diff = az - lastAzimuth;   if (diff > 180)      diff -= 360;   if (diff < -180)      diff += 360;    lastAzimuth = az;   totalChange += diff;   return totalChange / 360; } 

Answers 4

Visualize what I will say and you'll definitely hit your goal in no time. As you don't need to think of the full 360 degree, but you can take half of that and use the signs differences to your advantage.

Take a look at this figure : 360 Rotation

We have a circle that is divided to two sides (left and right).

The left side will take negative 180 degree. (West Side).

The right side will take positive 180 degree. (East Side).

Current positing will be always 0 as (North) and positive 180 as (South).

IF the compass goes positive (meaning goes to the right direction)

Then add +1 on each turn.

IF the compass goes negative (meaning goes to the left direction).

Then subtract -1 on each turn

IF the compass hit OR is 0, then it's current position (NORTH).

IF the compass hit OR is 90, then it's (East).

IF the compass hit OR is 180, then it's (South)

IF the compass hit OR is -90, then it's (West).

This will turn out that whenever the person goes East, the counter will add +1 until it reaches 180, Then it'll change from positive to negative, which will subtract -1 on each turn until it reaches 0. That would be a full 360 rotation.

Read More

Tuesday, January 24, 2017

How to get RotationMatrix from yaw, pitch and roll

Leave a Comment

Hi I managed to find yaw, pitch and roll from acceleratoin and magnetic sensor in my Android app. I now want to rotate my Camera Target(min3d) around a point in my scene according to does angles. The result is to be able to look in a 3d scene by moving the android device around. I've been trying for days almost read all related answers in SO but I just can't have it work.

The movement I get has absolutely no sens. I verified that my yaw is between 0-360 and is correct, pitch is between -90 and 90 and is correct and finally the roll is between -180 and 180 and is consistent.

Basically I am doing matrix rotation and multiplication by my target and up vector.

float[] rotation = new float[16];    Matrix.setIdentityM(rotation, 0); Matrix.rotateM(rotation, 0, (float) Math.toDegrees(roll), 0, 0, 1);          Matrix.rotateM(rotation, 0, (float) Math.toDegrees(pitch)+90f, 1, 0, 0);         Matrix.rotateM(rotation, 0, (float) Math.toDegrees(-azimut), 0, 1, 0);        float[] target = new float[4]; float[] source = new float[]{0,0,150,0};     Matrix.multiplyMV(target, 0,rotation, 0, source, 0); float targetX = target[0] + 0; float targetY = target[1] + 150; float targetZ = -target[2] + 0;  target = new float[4]; source = new float[]{0,1,0,0}; Matrix.multiplyMV(target, 0,rotation, 0, source, 0); float upX = target[0]; float upY = target[1]; float upZ = target[2];  scene.camera().target.x = targetX;               scene.camera().target.y = targetY; scene.camera().target.z = targetZ;       scene.camera().upAxis.x = upX; scene.camera().upAxis.y = upY; scene.camera().upAxis.z = upZ; 

Initially my target is at (0,0,150) and my up vector is (0,1,0).

Thank you for any help.

1 Answers

Answers 1

After the roll matrix, the target vector must be consistent because the target only aim axis.

Actually, your target is not vec3(0,150,150) the target is vec3(0,0,150) indeed. You rotate it and then add vec3(0,150,0). So think about it, vec3(0,0,150) is always vec3(0,0,150) if you rotate z-axis.

Update

Yes, rotateM() multiplies the matrix you set before and a matrix you set now, so logically there is no problem there.

 public static void rotateM(float[] rm, int rmOffset,         float[] m, int mOffset,         float a, float x, float y, float z) {     synchronized(sTemp) {         setRotateM(sTemp, 0, a, x, y, z);         multiplyMM(rm, rmOffset, m, mOffset, sTemp, 0);     }  public static void setRotateM(float[] rm, int rmOffset,         float a, float x, float y, float z) {     rm[rmOffset + 3] = 0;     rm[rmOffset + 7] = 0;     rm[rmOffset + 11]= 0;     rm[rmOffset + 12]= 0;     rm[rmOffset + 13]= 0;     rm[rmOffset + 14]= 0;     rm[rmOffset + 15]= 1;     a *= (float) (Math.PI / 180.0f);     float s = (float) Math.sin(a);     float c = (float) Math.cos(a);     if (1.0f == x && 0.0f == y && 0.0f == z) {         rm[rmOffset + 5] = c;   rm[rmOffset + 10]= c;         rm[rmOffset + 6] = s;   rm[rmOffset + 9] = -s;         rm[rmOffset + 1] = 0;   rm[rmOffset + 2] = 0;         rm[rmOffset + 4] = 0;   rm[rmOffset + 8] = 0;         rm[rmOffset + 0] = 1;     } else if (0.0f == x && 1.0f == y && 0.0f == z) {         rm[rmOffset + 0] = c;   rm[rmOffset + 10]= c;         rm[rmOffset + 8] = s;   rm[rmOffset + 2] = -s;         rm[rmOffset + 1] = 0;   rm[rmOffset + 4] = 0;         rm[rmOffset + 6] = 0;   rm[rmOffset + 9] = 0;         rm[rmOffset + 5] = 1;     } else if (0.0f == x && 0.0f == y && 1.0f == z) {         rm[rmOffset + 0] = c;   rm[rmOffset + 5] = c;         rm[rmOffset + 1] = s;   rm[rmOffset + 4] = -s;         rm[rmOffset + 2] = 0;   rm[rmOffset + 6] = 0;         rm[rmOffset + 8] = 0;   rm[rmOffset + 9] = 0;         rm[rmOffset + 10]= 1;     } else {         float len = length(x, y, z);         if (1.0f != len) {             float recipLen = 1.0f / len;             x *= recipLen;             y *= recipLen;             z *= recipLen;         }         float nc = 1.0f - c;         float xy = x * y;         float yz = y * z;         float zx = z * x;         float xs = x * s;         float ys = y * s;         float zs = z * s;         rm[rmOffset +  0] = x*x*nc +  c;         rm[rmOffset +  4] =  xy*nc - zs;         rm[rmOffset +  8] =  zx*nc + ys;         rm[rmOffset +  1] =  xy*nc + zs;         rm[rmOffset +  5] = y*y*nc +  c;         rm[rmOffset +  9] =  yz*nc - xs;         rm[rmOffset +  2] =  zx*nc - ys;         rm[rmOffset +  6] =  yz*nc + xs;         rm[rmOffset + 10] = z*z*nc +  c;     } } 

This android function rotateM() is a combined version of these three matrices below

void Matrix_Rotation_X(Matrix   &out_M,const float angle) {     float COS = (float)cos(angle);     float SIN = (float)sin(angle);     out_M.s[_0x0_]=  1.f;       out_M.s[_0x1_]= 0.f;    out_M.s[_0x2_]= 0.f;    out_M.s[_0x3_]= 0.f;     out_M.s[_1x0_]=  0.f;       out_M.s[_1x1_]= COS;    out_M.s[_1x2_]= SIN;    out_M.s[_1x3_]= 0.f;     out_M.s[_2x0_]=  0.f;       out_M.s[_2x1_]=-SIN;    out_M.s[_2x2_]= COS;    out_M.s[_2x3_]= 0.f;     out_M.s[_3x0_]=  0.f;       out_M.s[_3x1_]= 0.f;    out_M.s[_3x2_]= 0.f;    out_M.s[_3x3_]= 1.f;  }  void Matrix_Rotation_Y(Matrix   &out_M, const float angle) {     float COS = (float)cos(angle);     float SIN = (float)sin(angle);     out_M.s[_0x0_]=  COS;       out_M.s[_0x1_]= 0.f;    out_M.s[_0x2_]=-SIN;    out_M.s[_0x3_]= 0.f;     out_M.s[_1x0_]=  0.f;       out_M.s[_1x1_]= 1.f;    out_M.s[_1x2_]= 0.f;    out_M.s[_1x3_]= 0.f;     out_M.s[_2x0_]=  SIN;       out_M.s[_2x1_]= 0.f;    out_M.s[_2x2_]= COS;    out_M.s[_2x3_]= 0.f;     out_M.s[_3x0_]=  0.f;       out_M.s[_3x1_]= 0.f;    out_M.s[_3x2_]= 0.f;    out_M.s[_3x3_]= 1.f; }  void Matrix_Rotation_Z( Matrix  &out_M, const float angle) {     float COS = (float)cos(angle);     float SIN = (float)sin(angle);     out_M.s[_0x0_]=  COS;       out_M.s[_0x1_]= SIN;    out_M.s[_0x2_]= 0.f;    out_M.s[_0x3_]= 0.f;     out_M.s[_1x0_]=  -SIN;      out_M.s[_1x1_]= COS;    out_M.s[_1x2_]= 0.f;    out_M.s[_1x3_]= 0.f;     out_M.s[_2x0_]=  0.f;       out_M.s[_2x1_]= 0.f;    out_M.s[_2x2_]= 1.f;    out_M.s[_2x3_]= 0.f;     out_M.s[_3x0_]=  0.f;       out_M.s[_3x1_]= 0.f;    out_M.s[_3x2_]= 0.f;    out_M.s[_3x3_]= 1.f; } 

https://github.com/sunglab/StarEngine/blob/master/math/Matrix.cpp

Read More

Wednesday, April 13, 2016

Android synchronized onSensorChanged?

Leave a Comment

This is a followup to my question here: Android thread runnable performance

I'm having some difficulty wrapping my head around synchronized methods for my app

I'm polling the sensors and storing the sensor values into arrays whenever they change

float[] accelerometerMatrix = new float[3]; float[] accelerometerWorldMatrix = new float[3]; float[] gyroscopeMatrix = new float[3]; float[] gravityMatrix = new float[3]; float[] magneticMatrix = new float[3]; float[] rotationMatrix = new float[9];  class InsertHandler implements Runnable {         public void run() {             //get values from arrays and insert into db         }     }  public void onSensorChanged(SensorEvent event) {         sensor = event.sensor;          int i = sensor.getType();         if (i == MainActivity.TYPE_ACCELEROMETER) {             accelerometerMatrix = event.values;         } else if (i == MainActivity.TYPE_GYROSCOPE) {             gyroscopeMatrix = event.values;         } else if (i == MainActivity.TYPE_GRAVITY) {             gravityMatrix = event.values;         } else if (i == MainActivity.TYPE_MAGNETIC) {             magneticMatrix = event.values;         }          long curTime = System.currentTimeMillis();         long diffTime = (curTime - lastUpdate);          // only allow one update every POLL_FREQUENCY.         if(diffTime > POLL_FREQUENCY) {             lastUpdate = curTime;              //insert into database in background thread             executor.execute(insertHandler);         }     } 

Every 10ms, my app will take the current sensor values (from the arrays) and insert them into a database using a single thread executor. So the onSensorChanged method is both writing to the arrays, and reading from the arrays to write to database

My question is, should the onSensorChanged method be synchronized?

The most important thing is that I don't miss any data. Every 10ms I need to store the current sensor values - none can be missed.

So to my understanding, a synchronized method means that the UI thread will hold a lock, and it will write the sensor values to the arrays. During this time, the executor thread cannot read from those arrays due to the lock. Then the lock is lifted and the executor thread then locks, reads from arrays, and write to database, releases lock

I might be misunderstanding the use of synchronized methods here, especially given onSensorChanged is event driven and I'm not sure how that plays into it

But it seems that in a situation like this, I might not be inserting the most recent values every 10ms. When the UI thread establishes a lock, the executor thread can't write those values to the database. By the time the executor thread can write, the values would now be a few ms old and inaccurate

On the other hand, synchronization would mean that I dont have situations where the UI thread is changing the array values, while at the same time the executor thread is insert half changed values into the database

So for this type of situation where I need to insert the most recent/accurate sensor data every 10ms, should I be using a synchronized method?

1 Answers

Answers 1

Your current code is not thread safe as the Runnable is using the same arrays that the UI thread is writing to. Once you call executor.execute(insertHandler); there is no guarantee the UI thread won't get another sensor event and change one of the array values before the Runnable writes them to the database. It appears you understand this part.

To fix this I would not recommend using a synchronized block at all as it seems you just want to write out whatever values are stored in the arrays when diffTime > POLL_FREQUENCY. The onSensorChanged(...) method itself will only ever be called on the UI thread in your code so you don't have to worry about another thread changing the value of the arrays while in this method.

With all this said what you can do is store the current values of the arrays in a new instance of your Runnable class. I know it was suggested in your previous post to use the same instance but that will not make a noticeable difference. You can even verify by opening Android Monitor and check your memory usage as your application runs. By storing the current values it now won't matter if onSensorChanged() is called again before you write out the data because you already have a copy of the data you need that won't change.

Here is what I am suggesting in code:

class InsertHandler implements Runnable {     final float[] accelerometerMatrix;     final float[] accelerometerWorldMatrix;     final float[] gyroscopeMatrix;     final float[] gravityMatrix;     final float[] magneticMatrix;     final float[] rotationMatrix;      public InsertHandler(float[] accelerometerMatrix, float[] accelerometerWorldMatrix,             float[] gyroscopeMatrix, float[] gravityMatrix,             float[] magneticMatrix, float[] rotationMatrix) {         this.accelerometerMatrix = accelerometerMatrix;         this.accelerometerWorldMatrix = accelerometerWorldMatrix;         this.gyroscopeMatrix = gyroscopeMatrix;         this.gravityMatrix = gravityMatrix;         this.magneticMatrix = magneticMatrix;         this.rotationMatrix = rotationMatrix;     }      public void run() {         // use class field arrays values and insert into db     } } 

And then when you add the Runnable to the executor use:

Runnable insertHandler = new InsertHandler(accelerometerMatrix, accelerometerWorldMatrix,         gyroscopeMatrix, gravityMatrix, magneticMatrix, rotationMatrix); executor.execute(insertHandler); 
Read More