Как можно отследить краткосрочную траекторию 6-осевого инерциального измерительного блока?
Я искал и искал на форумах, писал одно сообщение за другим в DeepSeek и ChatGPT, но наткнулся на препятствие.
Сейчас я работаю над проектом, в котором хочу писать числа в воздухе, используя MPU6050, привязанный к кончику моего пальца вместе с микроконтроллером ESP32, поэтому я не хочу отслеживать положение в долгосрочной перспективе. Однако я не уверен, возможно ли это сделать. Датчик имеет гироскоп и акселерометр. Я попытался реализовать фильтр Mahony из библиотеки Adafruit AHRS, чтобы дважды интегрировать значения ускорения, исключить вектор силы тяжести и смотреть только на значения X и Z. На Python у меня есть программа визуализации, которая берет значения из плоскости XZ и строит график. Программа работает нормально, если писать очень быстро, не слишком крупно и сверху вниз (например, как вы бы написали 5, 3 или 2). Но для чисел вроде 8 или 6 приходится возвращаться к началу, и здесь программа дает сбой. Число становится искаженным и нечитаемым. Кроме того, когда я кладу датчик на стол, значения X и Z, как сообщается, становятся все более отрицательными с линейной скоростью, и я думал, что фильтр это отфильтрует... Есть ли что-то, что мне следует учесть? Есть ли какие-то упущения? Буду очень благодарен за совет!
Ниже представлена программа, которую я сейчас использую в Arduino IDE:
#include <Adafruit_MPU60.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_AHRS_Mahony.h>
Adafruit_MPU6050 mpu;
Adafruit_Mahony filter;
// Переменные положения и скорости
float vel_x = 0, vel_z = 0;
float pos_x = 0, pos_z = 0;
unsigned long last_time = 0;
bool recording = false;
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip");
while (1);
}
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
filter.begin(30); // Инициализируем фильтр
}
void loop() {
// Обработка команд запуска/остановки из Python
if (Serial.available()) {
char c = Serial.read();
if (c == 'S') {
recording = true;
pos_x = 0;
pos_z = 0;
vel_x = 0;
vel_z = 0;
last_time = millis();
} else if (c == 'E') {
recording = false;
}
}
if (recording) {
sensors_event_t accel, gyro, temp;
mpu.getEvent(&accel, &gyro, &temp);
float gx = gyro.gyro.x;
float gy = gyro.gyro.y;
float gz = gyro.gyro.z;
filter.updateIMU(gx, gy, gz, accel.acceleration.x, accel.acceleration.y, accel.acceleration.z);
// Получить кватернион и повернуть линейное ускорение в мировую систему отсчета
float q0, q1, q2, q3;
filter.getQuaternion(&q0, &q1, &q2, &q3);
float grav_x = 2.0f * (q1*q3 - q0*q2);
float grav_y = 2.0f * (q0*q1 + q2*q3);
float grav_z = 2.0f * (q0*q0 - 0.5f + q3*q3);
// Вычислить линейное ускорение (рама датчика)
float lax = accel.acceleration.x - grav_x * 9.81;
float lay = accel.acceleration.y - grav_y * 9.81;
float laz = accel.acceleration.z - grav_z * 9.81;
// Повернуть в мировую систему координат (упрощенно для плоскости XZ)
float ax_w = (1 - 2*q2*q2 - 2*q3*q3) * lax + (2*q1*q2 - 2*q0*q3) * lay + (2*q1*q3 + 2*q0*q2) * laz;
float az_w = (2*q1*q3 - 2*q0*q2) * lax + (2*q2*q3 + 2*q0*q1) * lay + (1 - 2*q1*q1 - 2*q2*q2) * laz;
// Интегрируем для получения позиции
float dt = (millis() - last_time) / 1000.0;
last_time = millis();
vel_x += ax_w * dt;
vel_z += az_w * dt;
pos_x += vel_x * dt;
pos_z += vel_z * dt;
// Отправляем данные в Python
Serial.print(pos_x);
Serial.print(",");
Serial.println(pos_z);
delay(30);
}
}
@Bobba, 👍-1
Обсуждение2 ответа
Если устройство на основе акселерометра IMU сообщает о движении в состоянии покоя, как правило, ему требуется калибровка:
Большинство, если не все, инерциальные измерительные блоки (ИИБ) требуют калибровки. Без калибровки постоянная ошибка смещения может быть интерпретирована как постоянное ускорение, которое можно интегрировать в постоянно возрастающую скорость, которую можно интегрировать в изменения местоположения.
Как правило, инерциальный измерительный блок (IMU) содержит датчики для трёх пространственных измерений, называемые датчиками X, Y и Z. При калибровке учитываются как смещение, так и амплитуда этих датчиков. Вкратце, калибровочные смещения X, Y и Z добавляются или вычитаются из исходных значений датчиков таким образом, чтобы результирующие максимальные (направленные к Земле) и минимальные (направленные от Земли) значения для любого одного датчика были одинаковыми. После применения смещений амплитуду двух датчиков, вероятно, потребуется скорректировать, чтобы она соответствовала амплитуде третьего. Выбор датчика для согласования, а какой для корректировки, произволен. Это описание подходит для акселерометра.
Смещение гироскопа определить проще. Оставьте гироскоп в состоянии покоя и снимите показания датчиков X, Y и Z. Считываемые значения можно умножить на -1 и использовать в качестве смещений калибровки гироскопа по осям X, Y и Z.
Калибровки, выходящие за рамки ответа на стековый обмен:
- Калибровка амплитуды гироскопа сложна и требует определённого уровня механического контроля. Короче говоря, поворот гироскопа в каждом из трёх положений на фиксированный угол может предоставить информацию, необходимую для расчёта значений калибровки амплитуды гироскопа.
- Датчики, не идеально ортогональные. Для этого требуется найти калибровочные коэффициенты в матрице 3x3, где три диагональных значения описаны выше в этом ответе. Однако оставшиеся шесть значений представляют собой (неожиданный) вклад других (предположительно идеально) ортогональных датчиков.
Вы столкнулись с распространённой проблемой: дрейфом акселерометра и ошибкой интегрирования с течением времени, особенно при двойном интегрировании для определения местоположения. Даже с фильтром Махони небольшие смещения акселерометра быстро накапливаются, приводя к дрейфу оценок местоположения, что объясняет искажение и дрейф значений в состоянии покоя.
Чтобы улучшить краткосрочное отслеживание:
Обнулите скорость, когда движение останавливается (например, исходя из малой величины ускорения).
Используйте пороговые значения, чтобы игнорировать очень малые значения (шум).
Ограничьте время интеграции — выполняйте интеграцию только во время письменного жеста.
Для повышения краткосрочной точности рассмотрите возможность использования фильтра Калмана или сглаживания скользящим окном.
Однако в целом отслеживание истинного положения с помощью 6-осевых инерциальных измерительных блоков (IMU) без внешних источников (таких как камеры или UWB) по своей сути ненадежно для чего-либо, кроме коротких, ограниченных движений.
Вам нужна помощь в реализации сегментации жестов или логики обнуления скорости?
- Считывание нескольких датчиков MPU 9250 с помощью мультиплексора TCA9548A
- Использование MPU6050 с ESP32 Cam - MPU Не обнаружено
- Несколько mpu9250 с использованием tca9548a с esp32
- LILYGO TTGO T-Display не может обнаружить акселерометр, гироскоп и датчик температуры MPU 6050
- Трудности получения значений угла от MPU6050.
- Можно ли получить значения только во время вибрации/движения с акселерометра (ADXL335/MPU6050)?
- esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2
- Драйверы для чипа последовательного порта CH9102X
попробуйте это https://forum.arduino.cc/t/finally-mpu6050-fifo-dmp-quaternion-code-for-arduino-made-easy/598424, @jsotola
Не уверен, что это ваша проблема, но в любом случае: 1. Не вызывайте
millis()дважды: вызовите его один раз и используйте одно и то же значение для вычисленияdtи для обновленияlast_time. 2. Не используйте (0, 0, 9.81) в качестве вектора гравитации: выполняйте калибровку перед каждым запуском., @Edgar BonetЯ не вижу никакой калибровки. В зависимости от используемых датчиков, это может означать, что перемещение по горизонтали или вертикали может быть практически нецелесообразным, если фактически не двигаться относительно Земли. Если это не так, я мог бы написать ответ с кратким описанием того, что требуется. Это проект POV? Часто эти датчики/программное обеспечение используются в компасах наклона. Не трясётся, как баллончик с краской. Интересно, нужно ли увеличить частоту дискретизации, чтобы успевать за изменениями движения. Кажется, я видел, как в проектах POV использовались простые методы. Например, датчики наклона. Затем предположим среднюю скорость человеческой руки., @st2000
Вы можете фильтровать фильтр Калмана., @liaifat85