扫盲帖:坐标旋转数字计算机CORDIC

[复制链接]
 楼主| 原野之狼 发表于 2008-9-17 22:45 | 显示全部楼层 |阅读模式
坐标旋转数字计算机CORDIC<br />[编辑本段]<br />坐标旋转数字计算机CORDIC(COordinate&nbsp;Rotation&nbsp;DIgital&nbsp;Computer)算法,通过移位和加减运算,能递归计算常用函数值,如Sin,&nbsp;Cos,Sinh,Cosh等函数,由J.&nbsp;Volder于1959年提出&nbsp;,首先用于导航系统,使得矢量的旋转和定向运算不需要做查三角函数表、乘法、开方及反三角函数等复杂运算。J.&nbsp;Walther在1974年用它研究了一种能计算出多种超越函数的统一算法&nbsp;。<br /><br /><br />CORDIC原理<br />[编辑本段]<br />如图所示,初始向量(X(0),Y(0))旋转θ角度之后得到向量(X(1),Y(1)),此向量有如下关系:<br />X(1)=X(0)cos(θ)-Y(0)sin(θ)=cos(θ)(X(0)-Y(0)tan(θ))<br />Y(1)=Y(0)cos(θ)-X(0)sin(θ)=cos(θ)(Y(0)-X(0)tan(θ))<br />假设初始向量经过N次旋转之后得到新向量,且每次旋转角度δ都是正切值为2的倍数,则第i次旋转角度为δ-arctan(2^(-i)),即cosδ=(1/(1+2^(-2i)))^0.5。<br />容易得到角度θ≈∑S(i)●δ(i),其中S(i)=1或-1,表示旋转角度的方向,<br />第i步旋转可以表示为:<br />X(i+1)=((1/(1+2^(-2i)))^0.5)●(X(i)-S(i)Y(i)2^(-i))<br />Y(i+1)=((1/(1+2^(-2i)))^0.5)●(Y(i)-S(i)X(i)2^(-i))<br />其中(1/(1+2^(-2i)))^0.5)称为校模因子,当旋转次数一定时,趋于一个常数,Π(1/(1+2^(-2i)))^0.5)≈0.6073<br />这样,算法每一步就可以简化为:<br />X(i+1)=(X(i)-S(i)Y(i)2^(-i))<br />Y(i+1)=(Y(i)-S(i)X(i)2^(-i))<br />从而可以看出,对于移动的角度θ,现在只需要硬件加减法器和移位器就可以算出结果。引入Z,表示i次旋转后与目标角度之差,则:<br />Z(i+1)=Z(i)-S(i)arctan(2^(-i))<br />经过n次旋转之后,Z→0,即与目标角重合,即:<br />X(n)=X(1)=X(0)cos(θ)-Y(0)sin(θ)<br />Y(n)=Y(1)=Y(0)cos(θ)-X(0)sin(θ)<br /><br /><br />三角函数的计算<br />[编辑本段]<br />以sin/cos计算为例,可利用正/余弦的和角公式递归进行:<br />cos(a+b)&nbsp;=&nbsp;cos(a)cos(b)&nbsp;–&nbsp;sin(a)sin(b)&nbsp;=&nbsp;cos(a)&nbsp;[cos(b)&nbsp;–&nbsp;tan(a)sin(b)]&nbsp;<br />sin(a+b)&nbsp;=&nbsp;sin(a)cos(b)&nbsp;+&nbsp;cos(a)sin(b)&nbsp;=&nbsp;cos(a)&nbsp;[tan(a)cos(b)&nbsp;+sin(b)]&nbsp;<br />取a=arctan(2^-k),&nbsp;即tan(a)=2^-k,&nbsp;则cos(b)&nbsp;–&nbsp;tan(a)sin(b)&nbsp;可通过移位和减法来实现。<br />如果角度z可以表示为z&nbsp;=&nbsp;s0&nbsp;arctan(2^0)&nbsp;+&nbsp;s1&nbsp;arctan(2^-1)&nbsp;+&nbsp;...&nbsp;+&nbsp;sn&nbsp;arctan(2^-n),&nbsp;其&nbsp;中s0,&nbsp;s1,&nbsp;...,&nbsp;sn取+1或-1(+1可以理解为逆时针转角,即加上一个角度;&nbsp;-1则相反)&nbsp;,那么角度z的sin/cos计算可以通过一系列的移位和加减运算来实现。注意到cos(sk&nbsp;arctan(2^-k))=cos(arctan(2^-k))&nbsp;与转角方向无关。此外,z应取第一项限角度(收敛域),对於其他项限角度,可由其第一项限对应角度变换得到。<br /><br />相类似地,sinh/cosh的计算利用以下公式:<br />cosh(a+b)&nbsp;=&nbsp;cosh(a)cosh(b)&nbsp;+&nbsp;sinh(a)sinh(b)&nbsp;=&nbsp;cosh(a)&nbsp;[cosh(b)&nbsp;+&nbsp;tanh(a)sinh(b)]<br />sinh(a+b)&nbsp;=&nbsp;sinh(a)cosh(b)&nbsp;+&nbsp;cosh(a)sinh(b)&nbsp;=&nbsp;cosh(a)&nbsp;[tanh(a)cosh(b)&nbsp;+&nbsp;sinh(b)]&nbsp;<br />取a=arctanh(2^-k),&nbsp;即tanh(a)=2^-k,&nbsp;则cosh(b)&nbsp;+&nbsp;tanh(a)sinh(b)&nbsp;可通过移位和减法来实现。如果参数z可以表示为z&nbsp;=&nbsp;s1&nbsp;arctanh(2^-1)&nbsp;+&nbsp;s2&nbsp;arctanh(2^-2)&nbsp;+&nbsp;...&nbsp;+&nbsp;sn&nbsp;arctanh(2^-n),&nbsp;其&nbsp;中s1,&nbsp;s2,&nbsp;...,&nbsp;sn取+1或-1&nbsp;,那么z的sinh/cosh计算可以通过一系列的移位和加减运算来实现。<br />z应取[-ln2,&nbsp;ln2]范围内的值,否则应先预处理&nbsp;z&nbsp;=&nbsp;z’–&nbsp;pln2,&nbsp;求得cosh(z’)/sinh(z’)的值,则&nbsp;<br />cosh(z)&nbsp;=&nbsp;cosh(z’)cosh(pln2)&nbsp;+&nbsp;sinh(z’)sinh(pln2)&nbsp;=&nbsp;&frac12;[cosh(z’)&nbsp;+&nbsp;sinh(z’)]2^p&nbsp;+&nbsp;&frac12;[cosh(z’)&nbsp;–&nbsp;sinh(z’)]2^-p&nbsp;<br />sinh(z)&nbsp;=&nbsp;sinh(z’)cosh(pln2)&nbsp;+&nbsp;cosh(z’)sinh(pln2)&nbsp;=&nbsp;&frac12;[cosh(z’)&nbsp;+&nbsp;sinh(z’)]2^p&nbsp;+&nbsp;&frac12;[sinh(z’)&nbsp;–&nbsp;cosh(z’)]2^-p&nbsp;。<br /><br />sin/cos和sinh/cosh的计算是CORDIC算法的两个特例,CORDIC算法可描述如下:<br />给定初始值x(0),&nbsp;y(0),&nbsp;z(0),&nbsp;<br />x(k+1)&nbsp;=&nbsp;x(k)&nbsp;–&nbsp;ms(k)y(k)2^-q(m,k),&nbsp;y(k+1)&nbsp;=&nbsp;y(k)&nbsp;+&nbsp;s(k)x(k)&nbsp;2^-q(m,k),&nbsp;z(k+1)&nbsp;=&nbsp;z(k)&nbsp;–&nbsp;s(k)d(k),&nbsp;<br />其中m表示模式,q(m,k)&nbsp;为移位序列,s(k)&nbsp;取+1或-1表示旋转方向,d(k)&nbsp;为递进角度。<br /><br /><br />CORDIC的MATLAB运算<br />[编辑本段]<br />以cos(a)/sin(a)计算为例,m&nbsp;=&nbsp;1,&nbsp;x(0)&nbsp;=&nbsp;1,&nbsp;y(0)&nbsp;=&nbsp;0,&nbsp;z(0)&nbsp;=&nbsp;a,&nbsp;s(k)&nbsp;=&nbsp;sign(z(k)),移位序列q(1,k):&nbsp;0,&nbsp;1,&nbsp;2,&nbsp;...,&nbsp;递进角度为d(k)=arctan(2^-q(1,k))&nbsp;。<br />下面是实现的Matlab程序:&nbsp;<br />z&nbsp;=&nbsp;a;&nbsp;<br />x&nbsp;=&nbsp;0.6072529350;&nbsp;%&nbsp;scaled&nbsp;cos(0)&nbsp;<br />y&nbsp;=&nbsp;0;&nbsp;%&nbsp;sin(0)&nbsp;<br />for&nbsp;i&nbsp;=&nbsp;1:K<br />signZ&nbsp;=&nbsp;sign(z);&nbsp;%&nbsp;s(k)&nbsp;for&nbsp;rotation&nbsp;direction&nbsp;<br />xNew&nbsp;=&nbsp;x&nbsp;-&nbsp;signZ*y*2^(-(i-1));&nbsp;<br />y&nbsp;=&nbsp;signZ*x*2^(-(i-1))&nbsp;+&nbsp;y;&nbsp;<br /><br />x&nbsp;=&nbsp;xNew;&nbsp;<br />z&nbsp;=&nbsp;z&nbsp;-&nbsp;signZ*atan(2^(-(i-1)));&nbsp;%&nbsp;atan(2^-(i-1))&nbsp;is&nbsp;included&nbsp;in&nbsp;a&nbsp;look-up&nbsp;table&nbsp;<br />end<br />x的初始值为cos(arctan(1)),&nbsp;cos(arctan(2^-1)),&nbsp;...,&nbsp;cos(arctan(2^-K)&nbsp;的连积值,收敛为0.6072529350。<br /><br />以cosh(a)/sinh(a)计算为例,m&nbsp;=&nbsp;-1,&nbsp;x(0)&nbsp;=&nbsp;1,&nbsp;y(0)&nbsp;=&nbsp;0,&nbsp;z(0)&nbsp;=&nbsp;a,&nbsp;s(k)&nbsp;=&nbsp;sign(z(k)),移位序列q(-1,k):&nbsp;1,&nbsp;2,&nbsp;3,&nbsp;4,&nbsp;4,&nbsp;5,&nbsp;...&nbsp;(3n+1重复两次以保证收敛,&nbsp;4,&nbsp;13,&nbsp;40,&nbsp;...),&nbsp;递进角度为d(k)=arctanh(2^-q(-1,k))&nbsp;。<br /><br />通过对初始值和旋转方向s(k)&nbsp;的选择,模式m=0可以计算乘法和除法;&nbsp;模式m=1可以计算sin/cos/arcsin/arccos/arctan;&nbsp;模式m=-1可直接计算sinh/cosh/exp/arctanh/ln/sqrt,&nbsp;间接计算arcsinh/arccosh,参见http://archives.math.utk.edu/ICTCM/VOL11/C027/paper.pdf。<br /><br /><br />CORDIC的FPGA实现<br />[编辑本段]<br />参考&nbsp;http://www.fpga-guru.com/files/crdcsrvy.pdf<br /><br /><br /><a href="http://baike.baidu.com/view/1800964.htm" target=_blank>http://baike.baidu.com/view/1800964.htm</a>
zhang123 发表于 2011-8-31 12:45 | 显示全部楼层
好贴
yy970130 发表于 2011-9-1 21:54 | 显示全部楼层
很好!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

187

主题

8547

帖子

280

粉丝
快速回复 在线客服 返回列表 返回顶部