@RD1706D

Как использовать RATE_VERY_FAST (Java, Android)?

Всем привет! Пишу программу для записи данных с акселерометра в csv файл на максимально возможной скорости, в документации к API Android есть несколько методов для работы с акселерометром, однако меня заинтересовали только два из них SENSOR_DELAY_FASTEST и RATE_VERY_FAST, если верить документации то RATE_VERY_FAST должна давать максимальную скорость опроса датчика (до 1700 гц), но почему то при замене SENSOR_DELAY_FASTEST на RATE_VERY_FAST скорость опроса становиться напротив в разы ниже (иногда может опускаться до 10 гц, при условии что с SENSOR_DELAY_FASTEST выдает 400 гц стабильно), в чем проблема?

Документация:

https://developer.android.com/reference/android/ha...
https://developer.android.com/reference/android/ha...

Код с RATE_VERY_FAST:

spoiler
import androidx.appcompat.app.AppCompatActivity;
import android.hardware.Sensor;
import android.hardware.SensorDirectChannel;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sm = (SensorManager) getSystemService(SENSOR_SERVICE);

        textView1 = (TextView) findViewById(R.id.Values);

        list = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);
        if (list.size() > 0) {
            sm.registerListener(sel, (Sensor) list.get(0), SensorDirectChannel.RATE_VERY_FAST);
        } else {
            Toast.makeText(getBaseContext(), "Error: No Accelerometer.", Toast.LENGTH_LONG).show();
        }
    }

    SensorManager sm = null;
    TextView textView1 = null;
    List list;

    StringBuilder info = new StringBuilder();

    final SensorEventListener sel = new SensorEventListener() {
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }

        public void onSensorChanged(SensorEvent event) {
            float[] values = event.values;
            String result0 = String.format("x: " + "%.20f", values[0]);
            String result1 = String.format("y: " + "%.20f", values[1]);
            String result2 = String.format("z: " + "%.20f", values[2]);
            info.append(result0 + "\n" + result1 + "\n" + result2 + "\n");
            //textView1.setText(result);
            textView1.setText("x: " +  values[0] + "\ny: " + values[1] + "\nz: " + values[2] + "\n");

        }
    };


    @Override
    protected void onStop() {
        if (list.size() > 0) {
            sm.unregisterListener(sel);
        }
        super.onStop();
    }
}


Код с SENSOR_DELAY_FASTEST:

spoiler
import androidx.appcompat.app.AppCompatActivity;
import android.hardware.Sensor;
import android.hardware.SensorDirectChannel;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sm = (SensorManager) getSystemService(SENSOR_SERVICE);

        textView1 = (TextView) findViewById(R.id.Values);

        list = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);
        if (list.size() > 0) {
            sm.registerListener(sel, (Sensor) list.get(0), SensorManager.SENSOR_DELAY_FASTEST);
        } else {
            Toast.makeText(getBaseContext(), "Error: No Accelerometer.", Toast.LENGTH_LONG).show();
        }
    }

    SensorManager sm = null;
    TextView textView1 = null;
    List list;

    StringBuilder info = new StringBuilder();

    final SensorEventListener sel = new SensorEventListener() {
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }

        public void onSensorChanged(SensorEvent event) {
            float[] values = event.values;
            String result0 = String.format("x: " + "%.20f", values[0]);
            String result1 = String.format("y: " + "%.20f", values[1]);
            String result2 = String.format("z: " + "%.20f", values[2]);
            info.append(result0 + "\n" + result1 + "\n" + result2 + "\n");
            //textView1.setText(result);
            textView1.setText("x: " +  values[0] + "\ny: " + values[1] + "\nz: " + values[2] + "\n");

        }
    };


    @Override
    protected void onStop() {
        if (list.size() > 0) {
            sm.unregisterListener(sel);
        }
        super.onStop();
    }
}
  • Вопрос задан
  • 120 просмотров
Решения вопроса 1
@Mercury13
Программист на «си с крестами» и не только
Давайте посмотрим, что представляет собой RATE_XXX и SENSOR_DELAY_XXX.
SENSOR_DELAY_FASTEST = 0
SENSOR_DELAY_GAME = 1
SENSOR_DELAY_UI = 2
SENSOR_DELAY_NORMAL = 3

RATE_STOP = 0
RATE_NORMAL = 1
RATE_FAST = 2
RATE_VERY_FAST = 3

Функция registerListener требует задержку в мкс, или одну из четырёх констант SENSOR_DELAY. Поставив RATE_VERY_FAST=3, вы реально поставили ему SENSOR_DELAY_NORMAL=3!

А куда же совать RATE? В SensorDirectChannel.configure! А сам SensorDirectChannel можно получить через SensorManager.createDirectChannel! Вот как-то так — и даже понимаю, откуда такая архитектура. Ну не может система, оптимизированная под низкое энергопотребление, 1700 раз в секунду пинать пользовательскую программу — программа получает управление намного реже, а информация с акселерометра накапливается в буфере памяти.

UPD. Есть и вторая причина. Обработка может затянуться более чем на 1/1700 секунды, и в это время датчик продолжит писать информацию в тот самый буфер.

UPD2. Другими словами, через callback и через буфер в памяти — две разных архитектуры. Первая обеспечит низкую задержку. Вторая — высокую (причём стабильно высокую!) частоту опроса, но задержка от регистрации до обработки, скорее всего, будет побольше.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы