Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compass - Track number of full 360 degree rotations

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;
        }
    }
}
like image 279
pez Avatar asked Oct 29 '22 06:10

pez


2 Answers

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.

like image 60
Ankit Arora Avatar answered Nov 13 '22 07:11

Ankit Arora


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;
}
like image 29
Michaël Roy Avatar answered Nov 13 '22 07:11

Michaël Roy