当前位置:   article > 正文

利用CORDIC算法计算三角函数_sin cordic

sin cordic

这里主要先介绍如何利用CORDIC算法计算固定角度ϕcos(ϕ)sin(ϕ)值。

一般利用MATLAB计算三角函数时,用cos举例,只需要输入相应的cos(ϕ)便自动计算出来了。但是如果是硬件处理或者没有那么方便的函数时,该如何计算cos(ϕ)的值呢?

有一种最傻瓜的方式是用rom存储0o90o所有的余弦值,然后用查表的方法计算,但随着精度要求的提升,需要存储的值会越来越多,这是不合适的。那么有没有一种用较少资源且能较快计算出高精度三角函数值的方法呢?有!这就是CORDIC算法可以做的事,算法不难,有一点三角函数和移位运算的基础就能看懂了,核心思想是数形结合计算三角函数,计算过程把乘法运算变成移位运算。cordic 三角函数算法的实现和matlab的仿真

为什么说是数形结合呢,让我们看下如何通过旋转求cosϕsinϕ。如下图可以看出,如果让初始坐标(x1,y1)x轴一个特定的位置,最后使其旋转ϕo到坐标(xn,yn)处,且满足xn2+yn2=1,那么cosϕ不就等于xnsinϕ不就等于yn了吗,这是后话。

下面首先引入一个在圆上的坐标旋转公式(不一定单位圆):

(1){x2=x1cosθy1sinθy2=x1sinθ+y1cosθ

注:(1)的推导

(1.1){x1=Acosαy1=Asinα

其中A为旋转圆半径,α(x1,y1)的角度值,图中红线与x轴夹角。则坐标(x2,y2)可以写为:

(1.2){x2=Acos(α+θ)=A(cosαcosθsinαsinθ)=x1cosθy1sinθy2=Asin(α+θ)=A(sinαcosθ+cosαsinθ)=x1sinθ+y1cosθ

推导完毕。

我们继续看式(1)(1)也可以写成:

(2){x2=cosθ(x1y1tanθ)y2=cosθ(y1+x1tanθ)

由于对(x2,y2)相当于同乘了一个常数cosθ,不影响旋转角度,只影响旋转后坐标到原点的距离。我们先不看它,得到:

(3){x2=x1y1tanθy2=y1+x1tanθ


一:乘法变移位

之前说的我们要把乘法运算变成移位运算,所以我们找到tanθ2i之间的对应关系,注意由于是变成移位操作,所以对应旋转的角度也是几个固定的值,但是通过旋转这几个固定的角度,旋转i次,最终也一定能转到我们需要的角度ϕ上(99.7oϕ99.7o)。

于是把(3)再改写为:

(4){x(i+1)=x(i)d(i)y(i)2iy(i+1)=y(i)+d(i)x(i)2i

这样,旋转θo就变成了移位、相加的操作。注意d(i)=±1表示旋转的逆、顺时针。

比如要旋转ϕ=66o,可以先转+45o45o<66o,再转+26.565o45o+26.565o66o,再转14.036o,最终会逼近66o。而整个运算仅仅进行了202122移位操作和加法操作。


二:cos累乘项

现在考虑把cosθ加回去,回到(2),且考虑旋转方向di和旋转角度θi,得到:

(5.1){x2=cosθ1(x1d1y1tanθ1)y2=cosθ1(y1+d1x1tanθ1)

进行下一次迭代(旋转),得到:

x3=cosθ2(x2d2y2tanθ2)=cosθ2(cosθ1(x1d1y1tanθ1)d2cosθ1(y1+d1x1tanθ1)tanθ2)=cosθ1cosθ2(x1d1y1tanθ1d2y1tanθ2d2d1x1tanθ1tanθ2)

y3=cosθ2(y2+d2x2tanθ2)(5.2)=cosθ2(cosθ1(y1+d1x1tanθ1)+d2cosθ1(x1d1y1tanθ1)tanθ2)=cosθ1cosθ2(y1+d1x1tanθ1+d2x1tanθ2d2d1y1tanθ1tanθ2)

可以看到每次旋转都可以提取出cosθitanθi已经用移位替代了。接下来只用计算i=1Ncosθi就行了,且i=1Ncosθi只跟迭代次数有关,大概收敛到0.607。确定了迭代次数后,可以预先把i=1Ncosθi算出来。


三:累计旋转角度与旋转方向

现在考虑最后一个问题,如何确定每次迭代的旋转方向di呢?其实定义一个累计旋转角度zi

(6)zi+1=zidiθi=zidi2i

z1等于目标角度值,然后每次迭代作个判断就好,如果zi>0,说明当前旋转还没转到目标角度,di+1=1;如果zi<0,说明当前旋转超过了目标角度,di+1=1

当我们最终转到了目标角度ϕ时,比如ϕ=66o,可以此时zi已经很小趋近于零了。

另外,在作比较判断时,单次旋转角度θi则还是需要通过查一次arctan(2i)表得到,但这个表比起文章开头说的傻瓜式查表要小太多了。


四:计算cos和sin值

由开始所说的数形结合可以推出,假设只旋转一次把(x1,y1)转到(xn,yn),有:

(7){xn=x1cosϕy1sinϕyn=x1sinϕ+y1cosϕ

按第一节所说的,把一次就旋转到位用很多次旋转替代,每次旋转后坐标到原点的距离比上一次都大了1cosθi倍,所以如果我们把(x1,y1)设为(i=1ncosθi,0),那么最后(xn,yn)到原点的距离就为1,cosϕ就等于xnsinϕ就等于yn

这样就只用通过(4)(6)的移位、相加、一次查表,再迭代十多次,就能计算cosϕsinϕ值啦!

其实用CORDIC算法还能计算arctan、sinh、cosh等值,以后学习了再来补充进阶版。


五:完整MATLAB代码

  1. clc, clear, close all;
  2. %% 初始计算cos累乘值
  3. N = 16; % 设置迭代次数16
  4. Nprod(1) = 1;
  5. for i = 1 : N
  6. Nprod(i + 1) = Nprod(i) * cos(atan(2^(-(i - 1))));
  7. end
  8. %% Cordic算法计算cos、sin值
  9. x(1) = Nprod(N); % 横坐标初始值赋为cos累乘值
  10. y(1) = 0; % 纵坐标初始值赋为0
  11. z(1) = 66 / 180 * pi; %目标旋转角度值,66°,注意转化成弧度值
  12. d(1) = 1; %旋转方向,初始肯定为1
  13. for i = 1 : N
  14. x(i + 1) = x(i) - d(i) * y(i) * 2^(-(i - 1)); %移位运算,公式(4)
  15. y(i + 1) = y(i) + d(i) * x(i) * 2^(-(i - 1)); %移位运算,公式(4)
  16. z(i + 1) = z(i) - d(i) * atan(2^(-(i - 1))); %计算累计旋转角度,查一次表,公式(6)
  17. if z(i + 1) >= 0 % 判断下一次的旋转方向
  18. d(i + 1) = 1;
  19. else
  20. d(i + 1) = -1;
  21. end
  22. end
  23. COS = x(N) % 输出cos66的值
  24. SIN = y(N) % 输出sin66的值

六:参考文章

[1]:什么是CORDIC算法

[2]:基于FPGA的CORDIC算法实现——Verilog版_cordic算法详解 一休哥-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/625505
推荐阅读
相关标签
  

闽ICP备14008679号