odriver 之 SVM

源码

SVM 函数的 alpha 和 beta 的值是经过了标幺化,基准值为 (最大相电压),也就是说 alpha 和 beta 的范围是 [-1,1]。约束:alpha-beta 向量的大小不得大于 $ $。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Compute rising edge timings (0.0 - 1.0) as a function of alpha-beta
// as per the magnitude invariant clarke transform
// The magnitude of the alpha-beta vector may not be larger than sqrt(3)/2
// Returns true on success, and false if the input was out of range
std::tuple<float, float, float, bool> SVM(float alpha, float beta) {
float tA, tB, tC;
int Sextant;

if (beta >= 0.0f) {
if (alpha >= 0.0f) {
//quadrant I
if (one_by_sqrt3 * beta > alpha)
Sextant = 2; //sextant v2-v3
else
Sextant = 1; //sextant v1-v2
} else {
//quadrant II
if (-one_by_sqrt3 * beta > alpha)
Sextant = 3; //sextant v3-v4
else
Sextant = 2; //sextant v2-v3
}
} else {
if (alpha >= 0.0f) {
//quadrant IV
if (-one_by_sqrt3 * beta > alpha)
Sextant = 5; //sextant v5-v6
else
Sextant = 6; //sextant v6-v1
} else {
//quadrant III
if (one_by_sqrt3 * beta > alpha)
Sextant = 4; //sextant v4-v5
else
Sextant = 5; //sextant v5-v6
}
}

switch (Sextant) {
// sextant v1-v2
case 1: {
// Vector on-times
float t1 = alpha - one_by_sqrt3 * beta;
float t2 = two_by_sqrt3 * beta;

// PWM timings
tA = (1.0f - t1 - t2) * 0.5f;
tB = tA + t1;
tC = tB + t2;
} break;

// sextant v2-v3
case 2: {
// Vector on-times
float t2 = alpha + one_by_sqrt3 * beta;
float t3 = -alpha + one_by_sqrt3 * beta;

// PWM timings
tB = (1.0f - t2 - t3) * 0.5f;
tA = tB + t3;
tC = tA + t2;
} break;

// sextant v3-v4
case 3: {
// Vector on-times
float t3 = two_by_sqrt3 * beta;
float t4 = -alpha - one_by_sqrt3 * beta;

// PWM timings
tB = (1.0f - t3 - t4) * 0.5f;
tC = tB + t3;
tA = tC + t4;
} break;

// sextant v4-v5
case 4: {
// Vector on-times
float t4 = -alpha + one_by_sqrt3 * beta;
float t5 = -two_by_sqrt3 * beta;

// PWM timings
tC = (1.0f - t4 - t5) * 0.5f;
tB = tC + t5;
tA = tB + t4;
} break;

// sextant v5-v6
case 5: {
// Vector on-times
float t5 = -alpha - one_by_sqrt3 * beta;
float t6 = alpha - one_by_sqrt3 * beta;

// PWM timings
tC = (1.0f - t5 - t6) * 0.5f;
tA = tC + t5;
tB = tA + t6;
} break;

// sextant v6-v1
case 6: {
// Vector on-times
float t6 = -two_by_sqrt3 * beta;
float t1 = alpha + one_by_sqrt3 * beta;

// PWM timings
tA = (1.0f - t6 - t1) * 0.5f;
tC = tA + t1;
tB = tC + t6;
} break;
}

bool result_valid =
tA >= 0.0f && tA <= 1.0f
&& tB >= 0.0f && tB <= 1.0f
&& tC >= 0.0f && tC <= 1.0f;
return {tA, tB, tC, result_valid};
}

函数主体上可以分为 2 大块,第一大块是个复合的 if 语句,用于判断扇区,第二个则是个 switch 语句,用于计算定时器的比较值,用于产生不同占空比的 PWM。

扇区判断

对于第一部分扇区判断,以第 1 扇区为例说明。

如图 1 所示,给定的$ \(值使得其合向量蓝色的\)vref\(位于第 1 扇区。分析一下位于第 1 扇区的\) \(有什么特点,最明显的就是 ,但这应该是位于第一象限的特点,还有 30°的范围不属于第 1 扇区,继续分析。每个扇区都是 60°,因此可以通过三角函数来确定\) \(和\) \(的关系。过 110 轴上任意点 P 做 100 轴的垂线 PA,则ΔOPA 显然为直角三角形,且∠PAO=90°,∠POA=60°,∠OPA=30°,此时,正好是\) \(的合向量恰好位于 110 轴的情形,当\)\(的值略小或\)$的值略大时,∠POA 都将小于 60°,合向量落入第 1 扇区。从数学上说

\[ \angle POA = arctan \frac{PA}{ OA} = arctan \frac{\beta}{ \alpha} < 60° \]

即可作为 1 扇区判断条件,坏消息是 arctan 在 MCU 上计算得慢,所以得换换思路。

\[ tan \angle POA = \frac{\beta}{ \alpha} \]

这是一个显而易见的结论,当合向量恰好位于 110 轴时$ tan60° = $ ,也就是$ = $ ,如果和程序中的表述一致的话,就是\(\alpha = \frac{1}{ \sqrt{3}} \beta\) 。当\(\beta\)减小\(\alpha\)不变或\(\alpha\)增大\(\beta\)不变时,合向量都将从 110 轴转向 1 扇区,反之则转入 2 扇区。

综上所述得到结论,当$> 0, > 0 $ 且 \(\beta > \sqrt{3} \alpha\) 合向量落在第 1 扇区; 当$> 0, > 0 $ 且 \(\beta < \sqrt{3} \alpha\),合向量落在第 2 扇区。

PWM 值计算

接下来聊一聊 PWM 比较值是如何计算的,这次以第 2 扇区为例,如图 2 所示。

在第 2 扇区的合向量是需要借助 010 和 110 这两个基本向量合成得到,传入 SVM 函数的参数 alpha 和 beta 的合向量是\(Vref\)。然后考虑将 \(\alpha\)\(\beta\)的值都分解到 010 和 110 这两个基本向量上。将\(\alpha\) 在 100 轴的端点称为 A 点,\(\beta\)端点称为 B 点。

先试着分解\(\alpha\)向量,过 A 点作 110(001)轴的平行线交 101 轴于 C 点。过 A 点作 010(101)轴平行线交 110 轴于 D 点。分析易得$ OAC OAD$ 都是等边三角形。因此,\(\alpha\)向量分解到 110 轴的长度也是\(\alpha\),分解到 010 轴的长度是\(- \alpha\)

然后分解\(\beta\)向量,过 B 点作 110 轴平行线交 010 轴于 E 点,过 B 点作 010 轴平行线交 110 轴于 F 点。易分析得 \(\bigtriangleup OBE 、 \bigtriangleup OBF\) 为底角为 30°的等腰三角形,需求 OE 和 OF 长度,且 OE=OF=BF=BE。过 E 点作 OB 垂线交于 G,则 \(\bigtriangleup EGB\)为直角三角形,且\(\angle EBG = 30°\)\(BE = \frac{2}{\sqrt{3}} BG\)\(BG = \frac{1}{2} \beta\)\(BE = \frac{1}{\sqrt{3}} \beta\) 为所求。 可以给结论了,110 轴上产生作用力的时间定义为 t2,010 轴上产生作用力的时间定义为 t3。则有:

\[ t3 = - \alpha + \frac{1}{\sqrt{3}} \beta \]

\[ t2 = \alpha + \frac{1}{\sqrt{3}} \beta \]

参考文献

https://zhuanlan.zhihu.com/p/506240030