-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdiscrete.go
72 lines (60 loc) · 1.73 KB
/
discrete.go
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
package lti
import (
"errors"
"gonum.org/v1/gonum/mat"
)
// Discrete represents a discrete LTI system.
//
// The parameters are:
// A_d: Discretized Ssystem matrix
// B_d: Discretized Control matrix
//
//
type Discrete struct {
Ad *mat.Dense
Bd *mat.Dense
C *mat.Dense
D *mat.Dense
ax, bu, sum mat.VecDense // Workspace for multAndSumOp
}
//NewDiscrete returns a Discrete struct
func NewDiscrete(A, B, C, D *mat.Dense, dt float64) (*Discrete, error) {
// A_d = exp(A*dt)
ad, err := discretize(A, dt)
if err != nil {
return nil, errors.New("discretization of A failed")
}
// B_d = Int_0^T exp(A*dt) * B dt
bd, err := integrate(A, B, dt)
if err != nil {
return nil, errors.New("discretization of B failed")
}
return &Discrete{
Ad: ad,
Bd: bd,
C: C,
D: D,
}, nil
}
// Predict predicts x(k+1) = A_discretized * x(k) + B_discretized * u(k)
func (d *Discrete) Predict(x *mat.VecDense, u *mat.VecDense) *mat.VecDense {
// x(k+1) = A_d * x + B_d * u
return multAndSumOp(d.Ad, x, d.Bd, u, d.ax, d.bu, d.sum)
}
//Response returns the output vector y(t) = C * x(t) + D * u(t)
func (d *Discrete) Response(x *mat.VecDense, u *mat.VecDense) *mat.VecDense {
// y(t) = C * x(t) + D * u(t)
return multAndSumOp(d.C, x, d.D, u, d.ax, d.bu, d.sum)
}
// Controllable checks the controllability of the LTI system.
func (d *Discrete) Controllable() (bool, error) {
// system is controllable if
// rank( [B, A B, A^2 B, A^n-1 B] ) = n
return checkControllability(d.Ad, d.Bd)
}
// Observable checks the observability of the LTI system.
func (d *Discrete) Observable() (bool, error) {
// system is observable if
// rank( S=[C, C A, C A^2, ..., C A^n-1]' ) = n
return checkObservability(d.Ad, d.C)
}