Проблемы с обнаружением вращения на 180 градусов - PullRequest
1 голос
/ 11 марта 2011

У меня есть алгоритм, который вычисляет сумму, которую повернул объект.

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

Вот код

 double newAngle = objOneAngle - objTwoAngle;
 if (newAngle< -180)
     newAngle += 360;
 else if (newAngle > 180)
     newAngle -= 360;

Любые мысли о том, как улучшить вышеприведенный код доиметь дело с поворотами на 180 градусов?

РЕДАКТИРОВАТЬ: Наиболее очевидный метод, который приходит на ум, это разделить положительные и отрицательные значения, а затем выбрать лучший набор, основанный на размере или какой-либо другой метрике, но долженбыть более простым, более элегантным решением?

Ответы [ 2 ]

3 голосов
/ 11 марта 2011

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

(1) Вычислить показатель «типичного вращения» некоторым способом, который не беспокоит расхождение: например, просто выберите одно из вращений наугад. (Если некоторые из них могут ошибаться, есть более надежные вещи, которые вы можете сделать.) Теперь отрегулируйте все ваши вращения так, чтобы «типичное» обнуление:

for (i=0; i<nSamples; ++i) {
  rotations[i] -= typicalRotation;
  if (rotations[i]<-180) rotations[i] += 360;
  else if (rotations[i]>180) rotations[i] -= 360;
}

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

(2) Что касается (1), но либо используйте повороты в вертикальном положении, либо отрегулируйте их на 180 градусов до и после обработки. Выберите, что делать, например, посчитав вращения между -90 и +90 и выяснив, являются ли они больше или меньше половины всех ваших вращений.

(3) Вместо усреднения углов поворота для каждого угла вычисляют (cos theta, sin theta) и усредняют те . Затем используйте atan2, чтобы преобразовать среднее обратно в угол. (Идея состоит в том, что углы являются «настоящими» точками на окружности, поэтому лучше работать с этими точками, а не с углами. Когда вы это делаете, неоднозначность между -180 и +180 градусами просто исчезает.)

Если то, что вы делаете, на самом деле является усреднением, мое любимое из них - 3. Ваш пробег может отличаться.

0 голосов
/ 11 марта 2011

Обычный способ справиться с ошибками округления в сравнениях с плавающей запятой - добавить небольшой допуск:

double newAngle = objOneAngle - objTwoAngle;
if (newAngle < -180.000001)
    newAngle += 360;
else if (newAngle > 180.000001)
    newAngle -= 360;

Таким образом, значения, достаточно близкие к 180, не изменяются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...