python反三⾓函数arctan_arctan()函数的查表算法
⽬标:实现反正切函数的查表算法,精度0.5°。
分析:
f(x) = arctan(x)函数单调但⾮线性,越接近原点处,斜率越⼤。
90°⽐较特殊,其值为正⽆穷⼤,只要得到的正切值tana⼤于114.59(89.5度对应的正切值),就可以认为是90度。
假如0-89.5°⽤⼀个查表实现,索引为正切值,值为⾓度值。tan89.5为115,假如⽤N点uint16_t型查表,需要保证
arctan(115 / N) < 0.5°
即 115 / N < 0.0087
可选的最⼩值为13219,意味着⾄少要建⽴⼀张13K×16的表,占⽤26KB的Flash,对于⼀般的MCU来说不可接受。
如果0-45°⽤⼀个查表实现,由于tan45°=1,根据上⾯的计算公式,可以得出N的最⼩值为114,这个N值对⼀般的MCU均可以接受,甚⾄可以增加⾄256点来提⾼精度。对于45°以上的⾓度,可以根据两⾓和的三⾓公式来得到,推导过程如下:
如果测量的正切值K⼤于1,那么根据最后的公式,可以求出⽐45°⼤的那个⾓度a,再加上45°就是实际的⾓度。⽽a的计算可以由256点查表来快速得到,这样就实现了⽤⼀个⼩容量查表计算90度以内的反正切值。
查表涉及两个数值:表索引idx和表的⾓度值angle[idx]。
索引值idx对应0-45°的正切值,由于这些值均⼩于1,采⽤整体扩⼤256倍的⽅法,将正切值就映射到了0-256的区间,从⽽索引idx 的范围为0-255。
⾓度值angle[]是uint16_t型的,⽽实际的范围为0-45,根据65536/45=1456,可以⽤Q12的表⽰⽅式来提⾼分辨率。
查表如下:
static const uint16_t tb_atan[256] = {
0, 229, 458, 687, 916, 1145, 1374, 1603,
1832, 2061, 2290, 2519, 2748, 2976, 3205, 3433,
3662, 3890, 4118, 4346, 4574, 4802, 5029, 5257,
5484, 5711, 5938, 6165, 6391, 6618, 6844, 7070,
7296, 7521, 7746, 7971, 8196, 8421, 8645, 8869,
9093, 9317, 9540, 9763, 9986, 10208, 10431, 10652,
10874, 11095, 11316, 11537, 11757, 11977, 12197, 12416,
12635, 12853, 13071, 13289, 13507, 13724, 13940, 14157,
14373, 14588, 14803, 15018, 15232, 15446, 15660, 15873,
16085, 16297, 16509, 16720, 16931, 17142, 17352, 17561,
17770, 17979, 18187, 18394, 18601, 18808, 19014, 19220,
19425, 19630, 19834, 20038, 20241, 20444, 20646, 20848,
21049, 21250, 21450, 21649, 21848, 22047, 22245, 22443,
22640, 22836, 23032, 23227, 23422, 23616, 23810, 24003,
24196, 24388, 24580, 24771, 24961, 25151, 25340, 25529,
25717, 25905, 26092, 26278, 26464, 26649, 26834, 27018, 27202, 27385, 27568, 27750, 27931, 28112, 28292, 28471, 28650, 28829, 29007, 29184, 29361, 29537, 29712, 29887, 30062, 30236, 30409, 30582, 30754, 30925, 31096, 31266, 31436, 31605, 31774, 31942, 32109, 32276, 32442, 32608, 32773, 32938, 33101, 33265, 33428, 33590, 33751, 33913, 34073, 34233, 34392, 34551, 34709, 34867, 35024, 35180, 35336, 35492, 35646, 35801, 35954, 36107, 36260, 36412, 36563, 36714, 36864, 37014, 37163, 37312, 37460, 37607, 37754, 37901, 38047, 38192, 38337, 38481, 38624, 38768, 38910, 39052, 39194, 39335, 39475, 39615, 39754, 39893, 40032, 40169, 40307, 40443, 40580, 40715, 40850, 40985, 41119, 41253, 41386, 41519, 41651, 41782, 41913, 42044, 42174, 42303, 42432, 42561, 42689, 42817, 42944, 43070, 43196, 43322, 43447, 43572, 43696, 43819, 43943, 44065, 44188, 44309, 44431, 44551, 44672, 44792, 44911, 45030, 45148, 45266, 45384, 45501, 45618, 45734, 45849, 45965, };
static int16_t calc_phase(int16_t real, int16_t imag)
{
int16_t
abs_real;
int16_t
abs_imag;
int16_t
phase;
uint16_t
zone;
uint32_t
tmp_tan;
uint32_t
delta_tan;
if (real
< 0)
{
三角函数查询表abs_real = -real;
zone = 1U;
}
else
{
abs_real = real;
zone = 0U;
}
if (imag
< 0)
{
abs_imag = -imag;
zone +=
2U; }
else
{
abs_imag = imag; zone =
0U; }
if (abs_imag
<= abs_real) {
tmp_tan =
(uint32_t)abs_imag<<8U;
tmp_tan /= abs_real;
phase =
tb_atan[tmp_tan]>>3U; }
else if
((abs_imag>>7U) <=
abs_real) {
delta_tan = ((uint32_t)(abs_imag -
abs_real))<<15U;
tmp_tan = (uint32_t)abs_imag + (uint32_t)abs_real; delta_tan /= tmp_tan;
delta_tan >>= 7U;
phase =
tb_atan[delta_tan]>>3U; phase += 5760; } else {
phase = 11520;
}
switch
(zone)
{
case 0U:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论