Если вам холодно, а отопление ещё не включили - забивайтесь в угол, там всегда 90 градусов
Потихоньку схожу с ума,
ковыряясь с теодолитом. Алгоритм почти готов, есть в нём своеобразная красота, что там нет НИ ОДНОГО УСЛОВИЯ, чистое "перемалывание чисел", сходится довольно шустро.
Раз за разом я "обжигался" на углах, когда они в произвольном месте перескакивают через 360°, и вдруг сегодня мне пришёл ответ на вопрос в заголовке. Всё потому, что и углы, и температуры - это АФФИННЫЕ ВЕЛИЧИНЫ!
Всех запугал, а под катом исключительно сложения, вычитания и деление на 2, математика за 1й класс...
Проблема, приведшая меня к помешательству, такова. Есть оптическая мишень:
(это мой дендрофекальный макет, сделанный в условиях жёсткого дефицита палок, реальную мишень с вашего позволения не показываю)
Теодолитом я навожусь на каждый отражатель, записывая все углы. Чтобы найти точное положение мишени (все 6 степеней свободы), алгоритму нужно дать какое-то начальное приближение. Начало координат мишени находится в её центре, мы так условились. Чтобы найти приблизительное направление на центр, кажется логичным взять среднее арифметическое от углов. Хотя бы от двух, которые ближе всего к центру:
Халява, сэр. Что здесь может пойти не так?
А что, если один угол равен 2°, а другой: 356°? Именно так показывает теодолит: если поехать влево от "нуля", сразу настанет 359°59'59'', и дальше в сторону уменьшения. Наша замечательная формула выдаст (2+356)/2=179°. Диаметрально противоположный результат, в кои-то веки В БУКВАЛЬНОМ СМЫСЛЕ.
Может, это потому что мы отсчитываем углы от 0° до 360°, а стоит нам перейти к диапазону -180°..+180° - и всё наладится? В рассмотренном случае будет всё хорошо: один угол 2°, а второй теперь -4°, получим (2-4)/2=-1°. Но если мы очутимся с противоположной стороны, с углами +178° и -176°, опять нарвёмся на такую же подлянку, получив (178-176)/2=1°, т.е опять ДИАМЕТРАЛЬНО ПРОТИВОПОЛОЖНЫЙ результат!
И что-то я задумался, а в какой момент совершается ошибка? Да, мы знаем, что у нас тут всё закольцовано, и 356° означает то же самое, что -4°, и ещё бесконечно много значений.
Но вот мы сложили два значения и получили 358°. Как, взглянув на это значение, мы можем догадаться, что оно "неправильное"? По нему самому ничего такого не скажешь. Ведь с тем же успехом у нас в начале могли быть два одинаковых угла по 179°. Сложив их, мы получаем то же самое 358° - никакого криминала, разделим на 2 - и получаем то, что надо.
Где-то тут я и вспомнил, как в своё время заморочался с
калькулятором физических величин PhysUnitCalc (версию 0.1 не качайте,
лучше 0.5, хотя и в ней есть пара неприятных глюков), и отдельную головную боль доставили температуры.
Дело в том, что приходится отличать температуру и РАЗНОСТЬ ТЕМПЕРАТУР. Скажем, 0 °С = 273,15 К, но при этом разность в 10 °С равна разности в 10 К. То есть, шкалы температур отличаются не только ценой деления, но и НАЧАЛОМ КООРДИНАТ. Вот потому температуру и называют иногда аффинной величиной, что пересчёт температуры описывается аффинным преобразованием, надо не только домножить на коэффициент, но и прибавить константу!
Так вот, у меня здесь с углами ровно та же история, есть углы поворота, а есть направления!
Угол поворота - это своего рода "оператор". Мы берём и крутим, независимо от того, где мы находились до этого. Никто не мешает нам провести поворот дважды, или трижды, поэтому мы спокойненько можем складывать углы поворота, и можем умножать их на константу, никто нам и слова дурного не скажет на это. Трижды повернуть на 10° - это значит повернуть на 30°, всё абсолютно логично.
А вот теодолит показывает НАПРАВЛЕНИЕ, например 2°. Цифра 2 сама по себе не имеет большого физического смысла. В зависимости от того, как теодолит повёрнут (и в какой момент оператор занулил угол), цифра может быть какой угодно. Повернём мы штатив на 10° - и наводясь на тот же самый объект, получим уже 12°. Можно одно направление вычесть из другого - мы получим угол поворота, который нужно совершить, чтобы из одного направления попасть в другое. Хитрость в том, что складывать направления нельзя! Понятно, никто нам не помешает это сделать, но результат будет, по сути, бессмысленным, в чём мы и убедились.
Объявив, что величины α, β и φ - это всё НАПРАВЛЕНИЯ, мы запрещаем складывать α и β! Расцеплять дробь и делить α на 2 отдельно мы тоже запрещаем. Но всё же есть способ правильно посчитать это выражение:
В числителе у нас разность направлений, т.е УГОЛ ПОВОРОТА. Здесь нет никаких проблем. Далее мы делим его на два - это также разрешено. Т.е мы находим такой угол, повернувшись на который дважды, мы придём к исходному. Хотя здесь может появиться неоднозначность. Определив исходный угол равным 360°, и поделив его на 2, мы получим 180°, что не противоречит нашему определению: дважды повернувшись на 180°, мы действительно повернёмся на 360°. Но для поворота ПО КРАТЧАЙШЕМУ ПУТИ надо всё-таки все углы поворота приводить к диапазону -180°..+180°, и уже потом делить...
И наконец, мы складываем направление и угол поворота, что даёт нам новое направление.
Проверим, заработает ли такой метод. Сначала α=2°, а β=356°. Вычитаем одно из другого, и получаем -354°. Но поскольку мы хотим поворот по кратчайшему пути, мы приводим этот угол в диапазон -180°..+180°, для этого прибавляем 360°, и получается 6°. Делим на 2, получаем 3°. И наконец, прибавляем β=356°, что даёт 359°. Это правильный ответ. Причём для НАПРАВЛЕНИЙ мы можем принимать такие диапазоны, которые сочтём нужным. Можно -180°..+180°, а можно 0°..360° (как сейчас, поскольку именно такой диапазон использует теодолит), или вообще их не ограничивать, и всё будет нормально работать.
И для очистки совести опробуем α=178° и β=-176°. Теперь их разность даст 354°. Приводим его к диапазону -180°..+180° (для поворота по кратчайшему пути), для этого вычитаем 360°, получается -6°. Делим на 2, получаем -3°. Прибавляем β, получаем -179°. И это снова правильный ответ, но если хочется, можем прибавить 360° и получить 181°. Главное, что при таких выкладках мы не можем ошибиться на 180°, как происходило ранее!
Подобным образом можно усреднять и больше углов, например, 3:
По крайней мере, пока все эти направления худо-бедно сгруппированы в одном месте, всё будет хорошо. Расположив направления равномерно по окружности, можно и эту штуку свести с ума, в смысле, от того, в каком порядке скормить данные, будет зависеть результат. Но тут и в принципе правильного ответа нет. Попытаться направления векторно усреднять - получим вообще НОЛЬ, который никакого угла не выражает.
Так что сиди мы в одной плоскости, можно было и не заморачиваться с комплексными числами, и в углах оно нормально заработает. Но когда добавляется второй угол, мне всё же комфортнее с векторным/кватернионным представлением... А то у теодолита ещё одна фича присутствует, он может на любой объект навестись ДВУМЯ РАЗНЫМИ СПОСОБАМИ:
То есть, и к горизонтальному углу (азимуту) прибавляешь 180°, и к вертикальному (углу места), и в итоге смотришь туда же. Как поясняют, так можно проверить точность механики теодолита, а если таковая хромает - то немножко улучшить результаты, на каждый объект наводясь дважды.
Немножко странно, что положение с вертикальным углом 180°..360° называют ПРЯМЫМ, а с углами 0°..180° - ОБРАТНЫМ.
В общем, тут если пытаться сравнивать конкретно УГЛЫ (сопоставлять реальные углы и расчётные), нужно было бы дополнительно эту особенность учитывать. А в векторах - красота, формулы для перехода от сферической системы координат в декартову корректно сработают и для прямого, и для обратного положения зрительной трубы, и далее всё однозначно.
Бонус: уголковый отражатель, как его видит теодолит.
UPD. Очередная оформительская подлянка: в TeX φ записывается как \varphi, а в HTML просто φ. И наоборот: ϕ это \phi, но ϕ!