ac_power/reference_frames/
dq.rs

1// Copyright 2023 Enphase Energy, Inc and Universal Interoperability for
2// Grid-Forming Inverters (UNIFI) Consortium.
3//
4//    Licensed under the Apache License, Version 2.0 (the "License");
5//    you may not use this file except in compliance with the License.
6//    You may obtain a copy of the License at
7//
8//        http://www.apache.org/licenses/LICENSE-2.0
9//
10//    Unless required by applicable law or agreed to in writing, software
11//    distributed under the License is distributed on an "AS IS" BASIS,
12//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13//    See the License for the specific language governing permissions and
14//    limitations under the License.
15
16use crate::trig::rotate;
17use crate::trig::{Cos, Sin};
18use core::ops::{Add, Mul, Neg, Sub};
19
20/// Balanced rotating reference frame
21#[derive(Debug, Copy, Clone, PartialEq)]
22pub struct Dq<T> {
23    pub d: T,
24    pub q: T,
25}
26
27/// Unbalanced rotating reference frame
28#[derive(Debug, Copy, Clone, PartialEq)]
29pub struct Dq0<T> {
30    pub d: T,
31    pub q: T,
32    pub zero: T,
33}
34
35impl<T: Add<Output = T>> Add<Dq<T>> for Dq<T> {
36    fn add(self, other: Dq<T>) -> Dq<T> {
37        let d = self.d + other.d;
38        let q = self.q + other.q;
39        Dq { d, q }
40    }
41    type Output = Dq<T>;
42}
43
44impl<T: Add<Output = T>> Add<Dq0<T>> for Dq<T> {
45    fn add(self, other: Dq0<T>) -> Dq0<T> {
46        let d = self.d + other.d;
47        let q = self.q + other.q;
48        let zero = other.zero;
49        Dq0 { d, q, zero }
50    }
51    type Output = Dq0<T>;
52}
53
54impl<T: Add<Output = T>> Add<Dq0<T>> for Dq0<T> {
55    fn add(self, other: Dq0<T>) -> Dq0<T> {
56        let d = self.d + other.d;
57        let q = self.q + other.q;
58        let zero = self.zero + other.zero;
59        Self { d, q, zero }
60    }
61    type Output = Dq0<T>;
62}
63
64impl<T: Add<Output = T>> Add<Dq<T>> for Dq0<T> {
65    fn add(self, other: Dq<T>) -> Dq0<T> {
66        let d = self.d + other.d;
67        let q = self.q + other.q;
68        let zero = self.zero;
69        Self { d, q, zero }
70    }
71    type Output = Dq0<T>;
72}
73
74impl<T: Sub<Output = T>> Sub<Dq<T>> for Dq<T> {
75    fn sub(self, other: Dq<T>) -> Dq<T> {
76        let d = self.d - other.d;
77        let q = self.q - other.q;
78        Self { d, q }
79    }
80    type Output = Dq<T>;
81}
82
83impl<T: Sub<Output = T> + Neg<Output = T>> Sub<Dq0<T>> for Dq<T> {
84    fn sub(self, other: Dq0<T>) -> Dq0<T> {
85        let d = self.d - other.d;
86        let q = self.q - other.q;
87        let zero = -other.zero;
88        Dq0 { d, q, zero }
89    }
90    type Output = Dq0<T>;
91}
92
93impl<T: Sub<Output = T>> Sub<Dq0<T>> for Dq0<T> {
94    fn sub(self, other: Dq0<T>) -> Dq0<T> {
95        let d = self.d - other.d;
96        let q = self.q - other.q;
97        let zero = self.zero - other.zero;
98        Self { d, q, zero }
99    }
100    type Output = Dq0<T>;
101}
102
103impl<T: Sub<Output = T>> Sub<Dq<T>> for Dq0<T> {
104    fn sub(self, other: Dq<T>) -> Dq0<T> {
105        let d = self.d - other.d;
106        let q = self.q - other.q;
107        let zero = self.zero;
108        Self { d, q, zero }
109    }
110    type Output = Dq0<T>;
111}
112
113impl<
114        T: Mul<Sin, Output = T>
115            + Mul<Cos, Output = T>
116            + Sub<Output = T>
117            + Add<Output = T>
118            + Copy
119            + From<f32>,
120    > Dq<T>
121{
122    pub fn zero() -> Self {
123        Self {
124            d: 0.0.into(),
125            q: 0.0.into(),
126        }
127    }
128    pub fn rotate(&self, cos: Cos, sin: Sin) -> Dq<T> {
129        let (d, q) = rotate(self.d, self.q, cos, sin);
130        Dq { d, q }
131    }
132}
133
134impl<T: From<f32>> Dq0<T> {
135    pub fn zero() -> Self {
136        Self {
137            d: 0.0.into(),
138            q: 0.0.into(),
139            zero: 0.0.into(),
140        }
141    }
142}