嵌入式系统上的三角函数

时间:2009-10-15 10:23:25

标签: c math embedded trigonometry

sincos函数速度很慢,需要大量资源才能在嵌入式系统上运行。如何以更节省资源和更快速的方式计算sincos函数?

11 个答案:

答案 0 :(得分:16)

计算TaylorFourier系列总是很耗时。

在嵌入式系统中,您应该考虑lookup tables

关于惠普如何在其早期科学计算器中优化此类计算的网络上可能还有一些有趣的信息。

我记得当时

答案 1 :(得分:10)

带插值的查找表无疑是最有效的解决方案。但是,如果你想使用更少的内存,CORDIC是计算trig函数值的一种非常有效的算法,通常在手持式计算器中实现。

作为一个侧面点,使用傅里叶级数表示这些函数没有任何意义,因为您只是创建了一个循环问题,即如何评估系列的sin / cos项。泰勒级数是一种众所周知的近似方法,但在许多情况下,误差大得令人无法接受。

您可能还想查看this question and its answers,关于Java的快速三角函数(因此代码可以轻松移植)。它提到了CORDIC和Chebyshev近似等。其中一个无疑将满足您的需求。

答案 2 :(得分:4)

取决于你需要它。如果您对角度精度不太满意(例如,如果最接近的度数可以),那么只需使用值的查找表。如果您没有FPU,请使用fixed-point

计算 sin / cos函数的一种简单方法是使用泰勒级数(如三角函数here所示)。您使用的术语越少,值越准确,但计算越快。

傅里叶级数计算需要知道一些正弦/余弦值。但是,如果您在大多数情况下将事物存储在frequency domain中,则可以节省计算 - 取决于您正在做什么。

答案 3 :(得分:3)

Dr. Dobb的文章:Optimizing Math-Intensive Applications with Fixed-Point Arithmetic对CORDIC算法有很好的解释,并为本文讨论的库提供了完整的源代码。

答案 4 :(得分:2)

  1. 查找 - 表
  2. Taylor series,就像你说的那样
  3. 请注意,对于查找表,您通常可以通过限制域来优化事物,例如:将角度表示为无符号字符,在圆周围只有256步,但也是一个非常紧凑的表。可以对值进行类似的操作,例如使用定点。

答案 5 :(得分:2)

请参阅Stack Overflow问题How do Trigonometric functions work?那里接受的答案解释了如何进行范围缩减的一些细节,然后使用CORDIC,然后进行一些进一步的优化。

答案 6 :(得分:0)

似乎有一个很好的伪代码示例here和显式代码here

但是,正如@unwind建议的那样,您可能希望尝试在一台不错的计算机上预先计算这些表,并将表加载到嵌入式设备中。

如果您的答案不一定非常精确,查找表会相当小,您将能够将其存储在设备的内存中。如果您需要更高的精度,则需要在设备中进行计算。这是记忆,时间和所需精度之间的权衡;答案取决于项目的具体性质。

答案 7 :(得分:0)

在某些情况下,人们可以使用IIR滤波器进行管理,调谐到所需频率的谐振。 看这里:http://www.ee.ic.ac.uk/pcheung/teaching/ee3_Study_Project/Sinewave%20Generation(708).pdf

答案 8 :(得分:0)

这可能有一些帮助/灵感: Magical square root in Quake III

答案 9 :(得分:0)

您可以查看这个用于8位AVR微控制器的任意定点库:  https://community.atmel.com/projects/afp-arbitrary-fixed-point-lib

编辑:链接已更新

答案 10 :(得分:0)

我参加派对有点晚了,但无论如何我想分享一个现成的高效解决方案,使用查找表(包括表生成器):DFTrig

DFTrig由两部分组成:

  • 查找表生成器tablegen(用Java编写,但并不重要)接收多个选项并生成C代码(带查找表的const结构)
  • 使用由tablegen生成的查找表的小C模块。

当然,查找表仅包含最少的信息:仅一个象限的正弦值,即[0, 90]度。这相当于计算任何角度的正弦/余弦。

行为非常可定制。您可以指定:

  • 查找表中每个项目乘以的因子(基于每个表);
  • 表格中每个项目之间的度数(基于每个表格); 表中的项目类型(整个C项目通用)。

因此,根据您的需要,您可以:

  • 使用max factor为整个应用程序生成单个表,以便C项目的任何子系统可以使用该单个表,提供所需的因子,如果请求的因子不是表的那个,则将重新计算;
  • 生成多个表,每个表都有ad hoc因子,C项目的每个子系统都使用其专用表。然后,可以按原样从表返回值,而无需重新计算;效果更快。

我在我的嵌入式项目中使用它,效果很好。