Перекрестная корреляция Arduino?

Как я могу написать легкий код кросс-корреляции для arduino? Я не мог найти никакого решения. Измерительная система содержит ультразвуковой датчик и сервопривод, который поворачивается от 45 до 135 градусов и измеряет расстояние от 4-300 см. Чем я собираю данные в массив, который содержит расстояния по отношению к углу. Система делает несколько подобных измерений, и программа находит перекрестную корреляцию между новыми и старыми массивами.

http://www.instructables.com/id/How-To-Make-an-Obstacle-Avoiding-Arduino-Robot/

, 👍2

Обсуждение

Вы хотите соотнести два сигнала реального времени или сигнал реального времени с предопределенным шаблоном? Насколько велико (по количеству выборок) окно, в которое вы хотите интегрироваться?, @Edgar Bonet

сигнал собран и чем кросс корр будет работать. длина сигнала-90., @acs

Не мог понять вашего предложения. Не могли бы вы обновить вопрос информацией о двух сигналах, которые вы хотите соотнести? Известны ли они во время компиляции? Должны ли они обрабатываться образец за образцом во время приобретения?, @Edgar Bonet

Я написал разреженный кросс-коррелятор, который работает с цифровым сигналом, дискретизированным по значениям таймера. Он работал на очень маленьком микроконтроллере. Если вы дадите нам больше информации о том, какой сигнал вы коррелируете, я буду рад опубликовать его здесь, @benathon

Есть ультразвуковой датчик.и сервопривод, который поворачивается от 45 до 135 градусов и измеряет расстояние от 4-300 см. теперь я собираю данные в массив, который содержит расстояния по отношению к углу. система делает несколько таких измерений, а затем программа находит корреляцию между новым и старым массивами., @acs


2 ответа


Лучший ответ:

4

Учитывая временной масштаб измерений, производительность не является проблемой. А поскольку вы не вычисляете в режиме реального времени, когда измеряются выборки, вы можете применить определение перекрестной корреляции как есть и вычислить ее в двойном цикле. Единственная трудность заключается в том, чтобы выяснить, что кросс-корреляция не может быть подходящим инструментом для этой работы... и найти правильный! Я предполагаю, что вы хотите оценить угол поворота между двумя измерениями.

Математическое определение перекрестной корреляции предполагает бесконечные массивы. На практике кросс-корреляция часто используется для нахождения короткого паттерна внутри длинного сигнала. В этом случае вычисление выполняется только для сдвигов, когда паттерн полностью перекрывает сигнал. Тогда длина результата равна

length(result) = length(signal) − length(pattern) + 1

В вашем случае, поскольку ваш паттерн является ранее измеренным сигналом, это даст результат с одной выборкой, который бесполезен.

Вместо этого вы можете вычислить интеграл для всех сдвигов, где есть любое перекрытие между паттерном и сигналом. Это эквивалентно заполнению сигнала нулем. У этого есть недостаток смещения результата: если ваш сигнал и паттерн оба безликие (положительные константы), вы найдете очень хороший пик при нулевом сдвиге!

Вы можете устранить это смещение, вычитая среднее значение как из сигнала , так и из паттерна и коррелируя(signal − avg (сигнал)) с (pattern − avg (паттерн)). Это все еще несет в себе предубеждение к “большим” функциям. Представьте себе, например, что после удаления средних значений у вас есть

pattern = [  0,   0, −20, +20,   0,   0];
signal  = [−50, +50,   0,   0, −20, +20];

Вы ожидаете, что ваш коррелятор найдет хорошее совпадение между [-20, +20] паттерна и [-20, +20] сигнала. Однако корреляция гораздо лучше с [-50, +50] сигнала. Вы можете попытаться облегчить эту проблему, вычислив вместо этого нормализованную кросс-корреляцию, но в лучшем случае вы сделаете оба совпадения одинаково хорошими.

Я предлагаю вам полностью забыть о корреляциях и вместо этого думать в терминах “хорошего соответствия”. Корреляции хороши для поиска масштабированных и сдвинутых копий паттерна внутри сигнала. Вы ищете только сдвинутые копии без масштабирования. Ваш вопрос должен звучать так: если вы сдвинете паттерн на некоторую величину, насколько хорошо он соответствует сигналу? Какая величина сдвига дает лучшую посадку? Канонический ответ на все вопросы “goodness of fit” состоит в том, чтобы минимизировать среднеквадратичную разницу между ними: вы вычисляете сумму

S = Σ(signal − shifted(pattern))²

Тогда среднеквадратичная разница равна

RMS(difference) = √(S/N)

где N-количество выборок, участвующих в сумме. Наиболее вероятный сдвиг-тот, который минимизирует эту ошибку. На практике вам не нужен квадратный корень, вы просто минимизируете

RMS(difference)² = Σ(signal − shifted(pattern))² / N

Вы можете реализовать эту формулу как есть, она совершенно проста. Просто имейте в виду, что N зависит от сдвига, так как это длина перекрытия. И избегайте очень маленьких перекрытий (то есть больших сдвигов).

Теперь, если вы развернете квадрат внутри суммы, вы можете обнаружить, что, в конце концов, это не так уж далеко от перекрестной корреляции... И кстати, все это не имеет никакого отношения к Arduino.

,

Мне нужна как задержка, так и корреляция информации. информация о задержке будет использоваться для оценки смещения, а отношение будет использоваться для определения важности предполагаемого смещения (действительно ли оно имеет значение или нет). Система будет работать как ультразвуковой радар на основе мертвого счета. Также я пытаюсь реализовать это [ссылка](http://paulbourke.net/miscellaneous/correlate/), @acs

У вас есть обе информации: 1) величина сдвига, которая дает лучшую подгонку, 2) среднеквадратичная разница при данном конкретном сдвиге., @Edgar Bonet


2

Это сработает. Никаких массивов или сложных вещей о cross blabla. Код находится в пределах 4-5 микрон

int mic1 = 2;// использование леонардо для внешних прерываний на этих выводах.
int mic2 = 3;
int mic3 = 7;

volatile unsigned long tid1 = 0; //Var для хранения метки времени в micros in.
volatile unsigned long tid2 = 0;
volatile unsigned long tid3 = 0;
volatile int stop1 = 0;//Флаги в прерываниях не запускаются снова. 
volatile int stop2 = 0;
volatile int stop3 = 0;


void setup() {
  
  
  pinMode(mic1, INPUT);
  pinMode(mic2, INPUT);
  pinMode(mic3, INPUT);
  pinMode(11, OUTPUT);//Например, зуммер подает звуковой сигнал, когда все триггеры в порядке!

  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(mic1), trig1, RISING);
  
  attachInterrupt(digitalPinToInterrupt(mic2), trig2, RISING);
  attachInterrupt(digitalPinToInterrupt(mic3), trig3, RISING);

}


void loop() {


  if (stop1 == 1 && stop2 == 1 && stop3 == 1) {
  

    stop1 = 20;
    stop2 = 20;
    stop3 = 20;

    


    delay(250); //ЭХО-задержка.

    tid1 = 0;
    tid2 = 0;
    tid3 = 0;

    stop1 = 0;
    stop2 = 0;
    stop3 = 0;


  }
}

void trig1() {

  if (stop1 == 0);
  tid1=micros();// Как написать это хардкорным способом, адресуя timer1, чтобы получить значение на основе clockcycles, я не знаю. Jus
  tid1=tid1;
  
  stop1 = 1;


}

void trig2() {

  if ( stop2 == 0);
  tid2=micros();
  tid2=tid2;
  
  stop2 = 1;

}


void trig3() {

  if ( stop3 == 0);
  tid3=micros();
  tid3=tid3;
  
  stop3 = 1;

}
,

У вас что-то странное происходит с if (stop1 == 0); и подобными строками. Обратите внимание на точку с запятой., @timemage

Я не вижу, как это даже отдаленно связано с вопросом, даже игнорируя необычный код., @Dave Newton