nabbla (nabbla1) wrote,
nabbla
nabbla1

Алг. ближ. дист - нахождение вектора (ФИНАЛ)

Вот и домучали практически, осталось получить дальность и ещё две координаты, практически "в плавающей точке". У нас на весь вектор общая "экспонента" (возведение в степень двойки) и 3 "мантиссы", причём дальность должна быть беззнаковой (по сути от 1 до 2), а поперечные координаты - со знаком, от -1 до +1.


Посмотрим старый код:
	;состояние регистров:
	;X=AfTransf
	;Y=QuatY
	;Z=MetricW
	;i=k=0
	;j=Exp
	;Inv=1
	;Acc=Scale
	;C = 2*Acc (побоч эффект DIV2S)
	FindVector	proc	
				k		3
				C		43648	;наше нулевое приближение к обр. величине
		@@Newton:	Acc		0		;занести двойку
				UFMS		[SP]	;Acc = 2 - a * x
				MULU		UAC		;Acc = Acc * x = x * (2- a*x), т.е итерация метода Ньютона
				Y		Rx								
				Z		Exp	
				i		1				
				C		UAC				
				kLOOP		@@Newton			
	;золотой ключик почти у нас в кармане
	;если на входе было 16384, то правильный результат 65536 не влезет в 16 бит, сократившись до нуля. 
	;это мы должны заметить по переполнению, только вот не соображу, оно должно ПОЯВИТЬСЯ, или исчезнуть?
				JGE		@@SkipOflo
				j++		0 			;раз не вмещается в мантиссу, значит добавим экспоненту, а в мантиссу нужно 32768 теперь.Ща найдём...
				C		32768 
		@@SkipOflo:	[Z+k]		j						
				[Z+1]		C

				X		Ty
	;и ещё осталось найти Ty, Tz
		@@vector:	MULSU		[Y+i]					
				[X+i]		Acc
				iLOOP		@@vector
	FindVector	endp		
AffineAlgorithm 	endp
;состояние регистров по окончании работы:
;X = Ty,
;Y = Rx,
;Z = Exp
;i=k=0,
;j=Exp
;Inv=1


Комментарии устарели даже сильнее, чем код. Z=MetricW - это из тех времён, когда "непосредственные значения" в коде могли быть только от -64 до +63, а всё что крупнее надо было упихивать в память и туда уже обращаться. Сейчас эти самые MetricW (веса, с которыми берутся две метрики) переехали прямо в код. Про "побочный эффект" от DIV2S тоже можно забыть, это раньше у меня получилось несколько "недокументированных команд", а сейчас всё и задокументировано, и от "побочных эффектов" они избавлены.

Чуть подрихтуем всё это безобразие...

	;состояние регистров:
	;X=AfTransf
	;Y=Matrix (первые 4 значения можно использовать как временные)
	;Z=QuatY (два нулевых значения, не надо их трогать)
	;i=k=0
	;j=Exp
	;Inv=1
	;C, Acc - пофиг (сейчас сотрём)
	;в [SP] лежит "мантисса" масштаба, которую надо обратить
	;в [SP+1] - либо 3, если дальняя дистанция, либо 5, если ближняя.
	FindVector	proc	

Так-то лучше!

А ещё появляется нехорошая мысль: пусть именно на месте 4 значений выходного вектора (экспонента и 3 мантиссы) будет располагаться AfTransf! В смысле, матрица с "исправленным креном". Ведь нам от неё нужен был только масштаб, его мы уже получили. Зато не нужно регистр лишний раз переиначивать :)

И ещё нужно всё-таки отнормировать кватернион. А то начну с его помощью вектора крутить (в алгоритме сопровождения), и они свою длину уменьшат сразу вдвое! Сорвётся всё сразу же.

В итоге получается такой код:
	;состояние регистров:
	;X=AfTransf=Exp   (это одно и тоже, просто в разное время)
	;Y=Matrix (первые 4 значения можно использовать как временные)
	;Z=QuatY (два нулевых значения, не надо их трогать)
	;i=k=0
	;j=Exp
	;Inv=1
	;C, Acc - пофиг (сейчас сотрём)
	;в [SP] лежит "мантисса" масштаба, которую надо обратить
	;в [SP+1] - либо 3, если дальняя дистанция, либо 5, если ближняя.
	FindVector	proc	
				k		3
				C		43648	;наше нулевое приближение к обр. величине
		@@Newton:	Acc		0		;занести двойку
				UFMS		[SP]	;Acc = 2 - a * x
				MULU		UAC		;Acc = Acc * x = x * (2- a*x), т.е итерация метода Ньютона
				Y		Rx								
				Z		QuatA
				i		1				
				C		UAC				
				kLOOP		@@Newton			
	;золотой ключик почти у нас в кармане
	;если на входе было 16384, то правильный результат 65536 не влезет в 16 бит, сократившись до нуля. 
	;это мы должны заметить по переполнению, только вот не соображу, оно должно ПОЯВИТЬСЯ, или исчезнуть?
				JGE		@@SkipOflo
				j++		0 			;раз не вмещается в мантиссу, значит добавим экспоненту, а в мантиссу нужно 32768 теперь.Ща найдём...
				C		32768 
		@@SkipOflo:	[X+k]		j						
				[X+1]		C

				X		Ty
	;и ещё осталось найти Ty, Tz
		@@vector:	MULSU		[Y+i]					
				[X+i]		Acc
				iLOOP		@@vector
		
				CALL		NormSiCo
				
	FindVector	endp	



Всё это вместе (алгоритм ближней дистанции) компилируется в 209 слов кода (418 байт). Сразу же запустим и посмотрим дамп памяти по окончании работы:


Всего уходит 343 мкс на выполнение, и если будет такое желание, можно на 33 мкс элементарно ускориться (сделать при нормировке кватерниона 4 итерации вместо 13). Дальше уже сложнее, но можно ещё примерно на те же 33 мкс "поджаться", но ценой увеличения кода. Но особой нужды не вижу, сейчас мы даже в обратный ход развёртки влезаем с огромным запасом, занимая где-то 1/5.

Синим выделен кватернион, в этот раз нормированный, норма его равна 1,0000139, лучше в 16 битах не сделаешь.

Фиолетовым вектор. Первое число - "экспонента", здесь ноль, что означает 20-1. (всегда ещё единичку вычитаем, чтобы получить диапазон дальности от 0,5 до 300 метров). Далее, идёт координата X, она же дальность. 0xAAD0 = 43728 ≈ 1,3345. То есть, дальность равна 20-1·1,3345 ≈ 0,667 метра.

Следующая координата Y, отвечающая за "курс" (влево-вправо). 0x07C2 = 1986 ≈ 0,0606. Умножаем на 0,5 метра - и получаем 0,0303 метра, или 3 сантиметра сдвиг вправо. Логично: мишень стоит довольно ровно по горизонтали, иначе она бы просто не влезла :) Но сдвиг вправо отчётливо виден:



Размер одного пятна как раз 3 см.

Наконец, координата Z, отвечает за "тангаж" (вверх-вниз). 0x4B9B = 19355 ≈ 0,5907. Помножаем на 0,5 метра и выходит 29,5 сантиметра сдвиг ВВЕРХ. Тут небольшая ошибка: я за "центр поля зрения" взял точку (512;512), что было бы логично для 1024х1024, но пока у нас изображение 1024х720, и центр мишени попадает примерно в Y=263. Вот и получилось, что по мнению алгоритма мы отодвинулись аж на 250 пикселей, а это должно соответствовать 5,9 градусам, что при дальности 0,667 метра даёт смещение в 6,8 сантиметра! Видать, тут значения больше в 4 раза, чем надо - не хотел точность терять.

Прицел 120, трубка 15, бац-бац И МИМО!

Как будто бы работает, но теперь всю эту историю калибровать надо. Точнее даже, "разрабатывать методику калибровки". Но ещё хочется сейчас оба алгоритма объединить наконец-то. Ставим ставки: влезет в 256 слов?
Tags: ПЛИС, математика, программки, работа, странные девайсы
Subscribe

Recent Posts from This Journal

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

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

  • Формулы приведения, что б их... (и atan на ТРЁХ умножениях)

    Формулу арктангенса на 4 умножениях ещё немножко оптимизировал с помощью алгоритма Ремеза: Ошибка уменьшилась с 4,9 до 4,65 угловой секунды, и…

  • Алгоритм Ремеза в экселе

    Вот и до него руки дошли, причина станет ясна в следующем посте. Изучать чужие библиотеки было лениво (в том же BOOSTе сам чёрт ногу сломит), писать…

  • atan на ЧЕТЫРЁХ умножениях

    Мишка такой человек — ему обязательно надо, чтоб от всего была польза. Когда у него бывают лишние деньги, он идёт в магазин и покупает какую-нибудь…

  • Ай да Пафнутий Львович!

    Решил ещё немного поковыряться со своим арктангенсом. Хотел применить алгоритм Ремеза, но начал с узлов Чебышёва. И для начала со своего "линейного…

  • atan(y/x) на двух умножениях!

    Чего-то никак меня не отпустит эта тема, всё кажется, что есть очень простой и эффективный метод, надо только его найти! Сейчас вот такое…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments