@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();
    }
}
  • Вопрос задан
  • 116 просмотров
Решения вопроса 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 и через буфер в памяти — две разных архитектуры. Первая обеспечит низкую задержку. Вторая — высокую (причём стабильно высокую!) частоту опроса, но задержка от регистрации до обработки, скорее всего, будет побольше.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы