11

I want to calculate the distance between the camera and the recognized object.For this I tried a lot of methods, I tried to find the angle between the object and the camera using accelerometer and then use

d = h * tan a

h is height of from from the base generally which is 1.4

and i tried to calculate the angle by using get orientation method. Kindly let me know where am I doing wrong. Its been more than 2 days I have been struggling with this requirement. We have looked into various Camera applications which are available on Android Store and have tried to understand the functionality of the same but nothing has been fruitful.

 mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
            accSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            magnetSensor = mSensorManager
                    .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            gravity = event.values;
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
            geoMagnetic = event.values;
        if (gravity != null && geoMagnetic != null) {
            float R[] = new float[9];
            float I[] = new float[9];
            boolean success = SensorManager.getRotationMatrix(R, I, gravity,
                    geoMagnetic);
            if (success) {
                /* Orientation has azimuth, pitch and roll */
                float orientation[] = new float[3];
                //SensorManager.remapCoordinateSystem(R, 1, 3, orientation);
                SensorManager.getOrientation(R, orientation);
                azimut = 57.29578F * orientation[0];
                pitch = 57.29578F * orientation[1];
                roll = 57.29578F * orientation[2];
            }
        }
    }


        captureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // get an image from the camera

                double d = (Math.tan(Math.toRadians(Math.abs(pitch))) * sensorHeight);
                Toast.makeText(
                        getApplicationContext(),
                        "Distance = "
                                + String.valueOf(d)
                                        + "m  Angle = "
                                        + String.valueOf(Math.toRadians(Math.abs(pitch))),
                        Toast.LENGTH_LONG).show();


            }
        });



protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, accSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
        mSensorManager.registerListener(this, magnetSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
    }
Rachit Tyagi
  • 658
  • 1
  • 9
  • 24
  • 1
    How would the angle relate to the distance? What if I stand on a balcony? Also, how can you ever measure the distance if you don't know the dimensions of the captured object? Plus, how much lens and optical sensor density information do you use? – class stacker Apr 11 '13 at 13:26
  • The purpose of the app to is find the distance between an object and the camera. Assuming both are standing on the same ground. We are not trying to measure the size of the object. – Rachit Tyagi Apr 11 '13 at 13:33
  • Also, you want to look at http://stackoverflow.com/q/4588485 – class stacker Apr 11 '13 at 13:35
  • It is not possible using just one camera. You have to know another information to position the object relatively to your device. It is not for nothing that the Kinect has a IR beamer + IR camera in addition to the normal camera. The orientation of your device will not give you any clue on the distance of an object in front of your camera. – Nicolas Dusart Apr 11 '13 at 13:37
  • I have already looked into it but have not been able to get the angle correctly as a result of which not able to use Tan to get the distance.The purpose is just to get appoximate distance. – Rachit Tyagi Apr 11 '13 at 13:38
  • Could you tell me what is this 57.29578F? – Anas Ahamed Oct 09 '17 at 07:18

2 Answers2

8

Your getRotationMatrix is probably returning false! You should copy the values to your own vectors so they don't get mixed up! Use the clone() method to do so!

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        gravity = event.values.clone();
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
        geoMagnetic = event.values.clone();

Using your code plus this change I was able to get the azimuth/pitch/roll values, without this change the success flag returns false:

Log.d("a", "orientation values: " + azimut + " / " + pitch + " / " + roll);
05-21 16:07:55.743: D/a(29429): orientation values: 77.71578 / 43.352722 / -152.39603
05-21 16:07:55.883: D/a(29429): orientation values: 175.26134 / 23.031355 / -148.72844
05-21 16:07:56.793: D/a(29429): orientation values: -146.3089 / 4.1098075 / -14.46417

You should use the PITCH value if you are holding the phone in portrait mode, if you are holding the phone in landscape mode you should use the ROLL value.

If you are holding the phone at a 1.4 height then you will have:

float dist = Math.abs((float) (1.4f * Math.tan(pitch * Math.PI / 180)));

Please note that you should use RADIANS and not DEGREES on the Math.tan function.

I tested here and the values seem to be valid!

thiagolr
  • 6,909
  • 6
  • 44
  • 64
  • What is THE PROBLEM? You wanted to know what you are doing wrong and you are not getting the values correctly. I used the exact same code with only the changed mentioned here and I was able to get the azimuth/pitch/roll values... – thiagolr May 21 '13 at 16:11
  • I am also getting the values but I have to calculate the distance between the object and the camera using the pitch(By using d = h*tan(a), where d is distance h is sensor height and a is the pitch angle). I have searched over the google and implement this method of getting the distance. But the distance calculated by using this pitch giving the wrong value. – Rachit Tyagi May 22 '13 at 06:17
  • Thanks for the answer now getting the valid values and I am using it in landscape mode but the problem now is this that the distance calculated is not accurate. For example if the distance is 10 mts then am getting 6.04 mts and if the distance is about 1 mt then am getting 0.024 mt. Please let me know where am doing wrong. If you are getting the accurate distance the could you please share your complete code. – Rachit Tyagi May 23 '13 at 14:18
  • Well, I solved the issue(s) from your question, now it is your turn to work on it... The sensors are extremely sensitive, a small movement will have great impact on the measurements. This is exactly how the other apps are calculating the distance... – thiagolr May 23 '13 at 17:09
  • thanks for the answer.By making some changes to into the code, I am getting the accurate values now. – Rachit Tyagi May 28 '13 at 10:10
  • 8
    please post the whole code here because it will help the community. – Abhijit Chakra Jul 08 '13 at 08:53
  • please post the whole code here because it will help the community – Bhaskar Jun 25 '15 at 08:33
  • how do i find sensor height –  Jun 30 '17 at 07:20
4

The final code is

mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
            accSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            magnetSensor = mSensorManager
                    .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        // TODO Auto-generated method stub
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            gravity = event.values;
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
            geoMagnetic = event.values;
        if (gravity != null && geoMagnetic != null) {
            float R[] = new float[9];
            float I[] = new float[9];
            boolean success = SensorManager.getRotationMatrix(R, I, gravity,
                    geoMagnetic);
            if (success) {
                /* Orientation has azimuth, pitch and roll */
                float orientation[] = new float[3];
                //SensorManager.remapCoordinateSystem(R, 1, 3, orientation);
                SensorManager.getOrientation(R, orientation);
                azimut = 57.29578F * orientation[0];
                pitch = 57.29578F * orientation[1];
                roll = 57.29578F * orientation[2];
            }
        }
    }


        captureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // get an image from the camera

                float d = Math.abs((float) (1.4f * Math.tan(pitch * Math.PI / 180)));
                Toast.makeText(
                        getApplicationContext(),
                        "Distance = "
                                + String.valueOf(d)
                                        + "m  Angle = "
                                        + String.valueOf(Math.toRadians(Math.abs(pitch))),
                        Toast.LENGTH_LONG).show();


            }
        });



protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, accSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
        mSensorManager.registerListener(this, magnetSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
    }
Rachit Tyagi
  • 658
  • 1
  • 9
  • 24