Category: космос

Category was added automatically. Read all entries about "космос".

QuatCore

Так есть ли толк в ковариационной матрице?

Задался этим вопросом применительно к своему прибору чуть более 2 недель назад. Рыл носом землю с попеременным успехом (раз, два, три, четыре), и вот, наконец-то заставил свою компьютерную модель всё посчитать, чтобы глянуть, "сколько это в процентах"!

Сценарий взят такой: располагаем мишень последовательно в 1 метре от прибора, в 2 метрах, и так далее, через метр, до 11 метров. Все углы (активные и пассивные) нулевые, и мы считаем, что способны разместить её абсолютно точно, т.е вся ошибка в измерениях, что есть - принадлежит моему прибору, Видеоизмерителю параметров сближения.

Сразу приведу 3 матрицы, соответствующие разным методам усреднения этих 11 опытов.



Это не совсем ковариационные матрицы - на главную диагональ я вместо дисперсий поставил среднеквадратичное отклонение в "понятных" единицах: угловых секундах, миллиметрах и микронах. А вне главной диагонали вместо ковариаций я привёл коэффициенты корреляции (от -1 до +1). И не стал верхний треугольник приводить, матрица симметричная.

Collapse )

Для данного сценария я чего-то такого и ожидал, честно говоря. Корреляция не сильно-то изменялась в процессе сближения, поэтому она не могла сильно помочь. Другое дело дисперсия - её знание позволяет повысить точность В РАЗЫ, по крайней мере, если мы берём много значений дальности. А, наверное, я всё-таки хочу дальность варьировать, чтобы вычленить из неё ещё и точное значение углового размера пикселя, то бишь "масштаб".

В принципе, дисперсия тоже относится к ковариационной матрице! То есть, по ТЗ нужно было выдавать лишь сами значения. Я предложил выдавать ещё и матрицу. Поможет ли эта матрица при юстировке? ЕЩЁ КАК! Нужно ли пускаться "во все тяжкие" ради дополнительных 2..4%? Не уверен. В принципе, такой выигрыш получится только если у нас очень точная модель ошибок измерений. Если сама по себе эта ковариационная матрица может не до конца соответствовать действительности, весь выигрыш может уйти в казино...

Big Data, чтоб их... (3)

"В предыдущих сериях": мой прибор выдаёт 6 значений: 3 координаты и 3 угла, т.е все 6 степеней свободы твёрдого тела. Причём ошибки измерения этих 6 значений сильно коррелированы между собой. Как именно - прибор знает, и выдаёт ковариационную матрицу шума измерений. Чтобы определить положение прибора на космическом корабле, я хочу провести где-нибудь N=10 опытов, располагая мишень на разных дальностях, измеряя её положение с помощью прибора, и, "контрольное измерение" - с помощью лазерного трекера, причём он будет мерять положение мишени в системе координат космического корабля. "Вычитая одно из другого", мы и должны раз за разом получать 6 параметров положения прибора на космическом корабле, но они будут зашумлены.

В прошлый раз я нашёл довольно простую формулу, с какими весами нужно сложить все 6N чисел, найденных за все эти N опытов, чтобы получить 6 искомых параметров, и чтобы свести шум к минимуму. Для этого нужно из ковариационных матриц шума измерений Qk (k-номер опыта) посчитать матрицу R:



и затем для каждого опыта найти свою матрицу весов, Ak



Тогда искомый вектор из 6 параметров выразится следующим образом:



(xk - вектор из 6 значений, измеренных в опыте k)

Интересный частный случай, если Q1=Q2=...=QN=Q, т.е от опыта к опыту ни дисперсии, ни ковариации не меняются. Такое может получиться, если мы дальность и углы не меняем особо, "топчемся на одном месте". Тогда данная формула очень существенно упрощается.

Collapse )
Sidious

А Королёв бы не возражал!

Чего-то в ближайшие дни услышал много негатива по поводу "киноэкипажа", хочу высказать индивидуальное мнение, которое хрен оспоришь. Считаю, что Королёву эта затея бы понравилась.

Во-первых, Королёв и сам очень любил киноэкипажи:

Korolev_with_dog.jpg

"Кино" - от корня "Кинос", собака.

А вот профессиональных космонавтов до мозга костей им. Каманина он как раз недолюбливал, о чём можно прочитать как у Чертока, так и в дневниках Каманина!

Collapse )
QuatCore

Тестируем atan1 на QuatCore

Пора уже перебираться на "железо" потихоньку. Решил начать с самого первого алгоритма, поскольку он уже был написан на ассемблере.

В программу внёс тестовый кусочек, где берётся 30 единичных векторов, распиханных по окружности с шагом 12° (от 0° и до 348°), и от каждого из них последовательно берётся atan1. Вектора просто засунул в неиспользуемую область памяти
[Spoiler (click to open)]
ORG	0x1A0

;тестовые данные для atan1
;набор из 30 векторов, через каждые 12 градусов, проверить работу на всей окружности
TestVec0x	Int16	32767
TestVec0y	Int16	0
TestVec1x	Int16	32052
TestVec1y	Int16	6813
TestVec2x	Int16	29935
TestVec2y	Int16 13328
TestVec3x	Int16	26510
TestVec3y	Int16	19261
TestVec4x	Int16	21926
TestVec4y	Int16	24351
TestVec5x	Int16	16384
TestVec5y	Int16	28378
TestVec6x	Int16	10126
TestVec6y	Int16	31164
TestVec7x	Int16	3425
TestVec7y	Int16	32588
TestVec8x	Int16	-3425
TestVec8y	Int16	32588
TestVec9x	Int16	-10126
TestVec9y	Int16	31164
TestVec10x	Int16	-16384
TestVec10y	Int16	28378
TestVec11x	Int16	-21926
TestVec11y	Int16	24351
TestVec12x	Int16	-26510
TestVec12y	Int16 19261
TestVec13x	Int16 -29935
TestVec13y	Int16 13328
TestVec14x	Int16	-32052
TestVec14y	Int16 6813
TestVec15x	Int16 -32768
TestVec15y	Int16 0
TestVec16x	Int16 -32052
TestVec16y	Int16 -6813
TestVec17x	Int16 -29935
TestVec17y	Int16 -13328
TestVec18x	Int16 -26510
TestVec18y	Int16 -19261
TestVec19x	Int16 -21926
TestVec19y	Int16 -24351
TestVec20x	Int16 -16384
TestVec20y	Int16 -28378
TestVec21x	Int16 -10126
TestVec21y	Int16 -31164
TestVec22x	Int16 -3425
TestVec22y	Int16 -32588
TestVec23x	Int16 3425
TestVec23y	Int16 -32588
TestVec24x	Int16 10126
TestVec24y	Int16 -31164
TestVec25x	Int16 16384
TestVec25y	Int16 -28378
TestVec26x	Int16 21926
TestVec26y	Int16 -24351
TestVec27x	Int16 26510
TestVec27y	Int16 -19261
TestVec28x	Int16 29935
TestVec28y	Int16 -13328
TestVec29x	Int16 32052
TestVec29y	Int16 -6813



и сразу после инициализации стека добавил вот этот код:
;здесь хотим проверить работу atan1
		Y		Matrix	;пока не используем, сойдёт
		k		29		;чтобы замучать 30 векторов
		X		TestVec29x
		Z		RT_PRF_NO	;отсюда начнут углы лежать (заголовок пожалеем)
@@k_loop:	CALL		atan1
		[Z+k]		[Y+1]	;перенесли угол куда хотели
		Acc		X
		SUB		2
		X		Acc
		kLOOP		@@k_loop


Я не питал иллюзий, что оно с первого же раза заработает правильно, поэтому не стал пока прошивать в ПЛИС, а запустил на симуляции. Очень удачно на осциллограмме мне как раз показали участок, где мы возвратились из процедуры atan1. И там я увидел, что регистр X указывает куда-то не туда.

Семён Семёныч: я забыл в atan1 всё-таки раскомментировать код, отвечающий за сохранение регистров в стек и восстановление их значений в конце процедуры, вот регистр X и "затирался".

Collapse )


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

РАБОТАЕТ!

Краткие итоги: 29 слов кода (58 байт) и 15 слов данных (30 байт). Точность: не хуже 2 единиц младшего разряда, преимущественно 0..1 единица. Время выполнения: около 21,6 мкс (540 тактов). Дополнительная функция: нахождение длины вектора с точностью не хуже 0,36%.

Да вообще-то, меня такое устраивает во всех отношениях :) Хотя есть некий спортивный интерес в получении полной точности, возможной в 16-битном представлении. В теории, алгоритм "atan на ЧЕТЫРЁХ умножениях" на это способен, ещё и уложится тактов в 100, но я не проверял ещё.

PS. Я неправильно ошибку считал: брал относительно исходных 12°, 24° и так далее, но ведь и представить их входными векторами точно я не мог. Сейчас это суммарная точность после двух операций. Возможно, если сравнивать с честно посчитанном atan(y/x) для двух целочисленных значений y,x, результат немного изменится в лучшую сторону. Ну и выборка пока маленькая.

PPS. Погоды сильно не делает. Там, где ошибка свыше 1,5 ЦМР, попробовал честно посчитать. Получил вместо 22 угл секунд ошибку в 21 угл секунду, ну да.
QuatCore

atan(y/x) на QuatCore

До сих пор у меня алгоритм для видеоизмерителя параметров сближения обходился без тригонометрии: все "кватернионные" вычисления удалось свести к сложениям и умножениям, включая и нормировку.

Но всё же, чтобы тупо выполнить условия ТЗ и выдать УГЛЫ, которые у нас просят (курс, тангаж, крен), нужно под самый конец преобразовать кватернион в эти углы.

Я так прикинул, для этого нужна ровно одна обратная тригонометрическая функция, которую условно назвал atan(y/x), не путать с atan2(y,x)!

Последняя выдаёт угол между осью OX и направлением на точку (x,y), с учётом квадранта. Как правило, ответ лежит в диапазоне от -pi до +pi, т.е "полный оборот". Но у нас сплошь используются половинные углы в кватернионах, поэтому результат надо ещё умножить на 2, и как раз такая "разборчивость к квадранту" оказывается излишней! Как раз-таки самый простой atan(y/x), выдающий значения от -pi/2 до pi/2, оказывается предпочтительнее, только вот "в явном виде" выполнять деление - наверное не лучшее решение. Когда мы приближаемся к плюс-минус pi/2, x стремится к нулю, аргумент арктангенса стремится к бесконечности и "достигает" её на краях.

Уж лучше этой функции дать два аргумента: x,y, т.е реализовать некий atan(y,x), в котором на самом деле мы пойдём "окольным путём".

Я хочу реализацию в целых 16-битных числах. Каким считать масштаб y,x - не так уж важно, главное, он один и тот же. А результат будет иметь формат Q3.13, т.е 3 бита перед запятой, 13 после запятой, со знаком, т.е диапазон от -4 до 3,9999 радиан. Цена младшего разряда около 25 угловых секунд, значит, точность порядка 12 угловых секунд, что соответствует точности задания угла кватернионом с 16-битными компонентами.

Хочу точность как минимум 0,1°, а лучше точнее. При этом максимально компактный код, т.к память "поджимает". А вот время выполнения меня не сильно заботит: нам отводится 200 мс на обработку измерений, а пока мы укладываемся в 200..300 мкс.

Collapse )

Похоже, нащупали неплохой способ, осталось его реализовать на ассемблере.

PS. Хотя забавно, как этот способ допускает максимальную ошибку при вычислении atan(0). У него получается не ноль, а 8 угловых секунд, которые, надеюсь, округлятся-таки до нуля при выдаче 16-битного результата. Хотя казалось бы, уж в нуле ошибиться никак нельзя, тут практически любой сходу даст правильный ответ!
QuatCore

Аффинный алгоритм+информационный обмен, минус два бага

Посидел глубоко в отладке, вроде разобрался, что к чему. Всё неправильное поведение свелось к двум багам, один в модуле RTC (Real Time Clock), второй - в программе, я в неё влез по дурости, показалось, что можно получше сделать, в итоге выкинув одну строчку, запорол одновременно и нормировку кватерниона, и компоненты Y,Z вектора параллельного переноса. Это ещё умудриться надо было...

Collapse )

Завтра проверю, что всё правильно - и придётся в очередной раз резко сменить род деятельности. Сегодня мне в РКК полтора часа мозги компостировали насчёт юстировки прибора. У нас для этого в теории существуют КПАшники (те, кто занимаются Контрольно-Проверочной Аппаратурой), целый отдел, но они самоустранились, сославшись на Стандарт Предприятия (СТП), по которому они делают только ту часть, что отправляется на входной контроль, это абсолютный минимум, способный лишь показать "ничего не повредили пока везли", а вот рабочее место, на котором проверяется львиная доля требований, а также всё, что касается работы заказчиков с прибором, включая измерение положения прибора на аппарате - должен придумать разработчик прибора, то есть я. Да, идейки были, но пора их оформить...
QuatCore

Аффинный алгоритм + информационный обмен

Возвращаемся к нашим баранам, к макету видеоизмерителя параметров сближения.

В нём готов и сколько-нибудь отлажен модуль информационного обмена, работающий автономно, без помощи процессора. И также готов модуль DMA (Direct Memory Access), позволяющий и процессору, и модулю информационного обмена обращаться к одной и той же оперативной памяти, но пока не отлажен.

Хочется попробовать всё это запустить "с нахрапу", но для этого надо программу подправить. Возьму пока "аффинный алгоритм", который у меня влез в "загрузочный сектор" (512 байт), но надо всю память перераспределить, в соответствии с этой табличкой:



Collapse )

На удивление долго память размечал. Вроде бы должен был "на автомате" практически сделать, но всё сомнения одолевали. Маленький милый поросёнок как-то внезапно превратился в ОГРОМНОГО КАБАНА! Мне по душе задачки поменьше, где можно как-то хитро извернуться и красиво решить, где всё очерчено хорошо. Но что делать, когда всё это соединяешь вместе, хочешь-не хочешь, получится толсто.

Теперь ещё есть желание переделать вход IN с UART, чтобы это не UART был как таковой, а "отмашка" от протокольного контроллера, сигнал к началу работы. OUT вообще "выкинуть" - и попробовать всё это запустить на железе, вдруг прям возьмёт и заработает? Это будет очень подозрительно...
QuatCore

"МКО" с CRC, работа над ошибками

В кои-то веки всё соединили вместе, начали тестировать и обнаружили две проблемы:

- не обеспечивается паузы между принятым сообщением и передаваемым. Доходит до того, что отвечать начинаем ещё до того, как передатчик окончит стоповый бит!
- нарушена логика обнаружения ошибки в сообщении: ещё во время приёма командного слова "зажигается" CRCerror и не "гаснет" вовремя.

Прежде чем двигаться дальше, надо это дело исправить, по возможности малой кровью.

Collapse )

Ладно, эти две проблемы устранили, потом обнаружили ещё одну, при передаче данных (CRC сбивается на 1 слово), её сейчас тоже обмозгуем. Должно быть решение, простое до безобразия, главное, его найти...
QuatCore

Тестируем "МКО" с CRC

Вроде как написали самую полную версию "протокольного контроллера МКО" (хоть и вместо настоящего МКО он пока использует UART), а ещё полудуплексный 16-битный приёмопередатчик с модулем CRC. Пора бы посмотреть, что они между собой дружат.

Для начала на симуляции. Но для этого нужно в ПЛИС "подружить" два приёмопередатчика между собой, чтобы они думали, что посередине линия передачи RS485. Т.е с одной стороны в этот модулёк будут поступать провода rxd (выход данных с приёмника), txd (вход данных на передатчик) и RW (0, если нужно принимать данные, 1, если нужно передавать). И с другой стороны то же самое. Причём rxd - двунаправленная линия, при RW=1 приёмник должен перевести свой выход на rxd в Z-состояние (высокое выходное сопротивление).

Как-то так:
module RS485dummyLine (input RW0, txd0, inout rxd0,
			input RW1, txd1, inout rxd1);
					
assign rxd0 = RW0? 1'bz : txd1;
assign rxd1 = RW1? 1'bz : txd0;					
									
endmodule


Фактически, передатчик одного модуля соединяется с приёмником соседнего (и наоборот), но приёмник "слепнет" во время работы собственного передатчика, тем самым моделируя полудуплекс.

И ещё "нарисуем" схему всего модуля информационного обмена (протокольный контроллер + память + часы реального времени + приёмопередатчик + CRC) в сборе:


Большинство выводов этой схемы - отладочные, посмотреть "что там творится". А по сути, "наружу" выходят:
- txd, rxd и RW - интерфейс с "физическим уровнем" приёмопередатчика,
- Mark - сигнал скорее всего от процессора (назначим ему отдельный адрес и декодер), что половина экспозиции кадра завершена. Устанавливает на выход часов реального времени метку, когда это произошло.

Весь остальной обмен должен будет идти через "общую" память, это сделаем, как только хреновину отладим. Хотя, также в отладочных целях, я наверное введу ещё остановку процессора в ожидании прихода "Синхронизация (с СД)", не готов я к тому, что процессор будет жить своей жизнью, перемалывая по 25 кадров в секунду, а мы будем получать данные "с какого повезёт".

Синтезируется такая схема в 240 ЛЭ, предельная частота 52,91 МГц. Злой рок: первое число неумолимо растёт, второе столь же неумолимо падает!

Впрочем, ещё одну вещь мы позабыли: контроллеру нужно как-то отличать между собой слова данных и командные слова! Он ожидает, что ему это сообщат прямым текстом, по проводу RXisData, руководствуясь полярностью синхроимпульса в МКО (Mil-Std 1553). Но в UART у нас нет полярности синхроимпульса, надо придумать костыль.

Collapse )

С нахрапу "прикрутить" CRC не получилось, немножко не рассчитал. И ещё всплыл старый должок с обеспечением паузы между приёмом и передачей ответного слова. Что ж, завтра будем исправлять.
QuatCore

"МКО (Mil-Std1553) через UART", часть 1

Громко подумали, пора начать ковыряние.

Вообще, я очень надеюсь, что написанный сейчас модуль практически без изменений подойдёт для "нормального" МКО. Там, разве что, ещё логику резервирования надо будет продумать, когда два приёмника, два передатчика, и ответ надо посылать по той шине, по которой мы получили запрос.

Сейчас идея, что этот контроллер работает независимо от процессора, напрямую обращаясь к памяти. Это "Оконечное Устройство" (ОУ, оно же Remote Terminal), т.е оно само не может инициировать информационный обмен, только отвечать контроллеру шины (КШ, Bus Controller).

И сделаем "задел" для реализации по ГОСТ 52070-2003 задания адреса оконечного устройства с помощью перемычек, хотя на первое время они будут "виртуальными" внутри ПЛИС :)

Не буду пытаться сделать "универсальный модуль на все времена", потому как неизбежно получится что-то вроде 1895ВА2Т, на которую под 300 страниц документации, где ещё попробуй разберись! Реализую лишь те функции, что нужны мне конкретно в этом приборе.

Начинаем традиционно с заголовка, тут он очень упитанный:
module MilStdRemoteTerminalController (input clk,
		//интерфейс с приёмником МКО
		input [15:0] D, input RXisData, input DataValid,
		//интерфейс с передатчиком МКО
		output [15:0] Q, output TXisData, output start, input TxBusy,
		//интерфейс с оперативной памятью (малого объёма, около 1000 слов)
		output [MemWidth-1:0] Addr, input [15:0] MemIn, input MemReady, output MemWrReq, output MemRdReq,
		//интерфейс с часами реал времени
		output sync, input [15:0] TimeStamp,
		//интерфейс с адресной заглушкой
		input [4:0] OurAddr, input AddrParity);
		
parameter MemWidth = 8;




Collapse )

Нда, снова громко подумали, написав аж 15 строчек кода... Продолжение следует! Там уже возьмёмся всерьёз.