@@ -23,9 +23,9 @@ struct NonLinModel{NT<:Real, F<:Function, H<:Function} <: SimModel{NT}
23
23
end
24
24
25
25
@doc raw """
26
- NonLinModel{NT}(f! ::Function, h! ::Function, Ts, nu, nx, ny, nd=0)
26
+ NonLinModel{NT}(f::Function, h::Function, Ts, nu, nx, ny, nd=0)
27
27
28
- Construct a nonlinear model from discrete-time state-space functions `f! ` and `h! `.
28
+ Construct a nonlinear model from discrete-time state-space functions `f` and `h`.
29
29
30
30
The state update ``\m athbf{f}`` and output ``\m athbf{h}`` functions are defined as :
31
31
```math
@@ -45,7 +45,7 @@ Nonlinear continuous-time state-space functions are not supported for now. In su
45
45
manually call a differential equation solver in `f` (see [Manual](@ref man_nonlin)).
46
46
47
47
!!! warning
48
- `f! ` and `h! ` must be pure Julia functions to use the model in [`NonLinMPC`](@ref),
48
+ `f` and `h` must be pure Julia functions to use the model in [`NonLinMPC`](@ref),
49
49
[`ExtendedKalmanFilter`](@ref), [`MovingHorizonEstimator`](@ref) and [`linearize`](@ref).
50
50
51
51
See also [`LinModel`](@ref).
@@ -61,82 +61,75 @@ Discrete-time nonlinear model with a sample time Ts = 10.0 s and:
61
61
```
62
62
"""
63
63
function NonLinModel {NT} (
64
- f! :: Function , h! :: Function , Ts:: Real , nu:: Int , nx:: Int , ny:: Int , nd:: Int = 0
64
+ f:: Function , h:: Function , Ts:: Real , nu:: Int , nx:: Int , ny:: Int , nd:: Int = 0
65
65
) where {NT<: Real }
66
- iscontinous = validate_fcts (NT, f!, h!)
67
- if iscontinous
68
- fc! = f!
69
- f! = let nx= nx, Ts= Ts, NT= NT
70
- ẋ = zeros (NT, nx)
71
- xterm = zeros (NT, nx)
72
- k1, k2, k3, k4 = zeros (NT, nx), zeros (NT, nx), zeros (NT, nx), zeros (NT, nx)
73
- function rk4! (x, u, d)
74
- xterm .= x
75
- fc! (ẋ, xterm, u, d)
76
- k1 .= ẋ
77
- xterm .= @. x + k1 * Ts/ 2
78
- fc! (ẋ, xterm, u, d)
79
- k2 .= ẋ
80
- xterm .= @. x + k2 * Ts/ 2
81
- fc! (ẋ, xterm, u, d)
82
- k3 .= ẋ
83
- xterm .= @. x + k3 * Ts
84
- fc! (ẋ, xterm, u, d)
85
- k4 .= ẋ
86
- x .+ = @. (k1 + 2 k2 + 2 k3 + k4)* Ts/ 6
87
- return x
88
- end
89
- rk4!
90
- end
66
+ ismutating_f = validate_f (NT, f)
67
+ ismutating_h = validate_h (NT, h)
68
+ f! = let f = f
69
+ ismutating_f ? f : (xnext, x, u, d) -> xnext .= f (x, u, d)
70
+ end
71
+ h! = let h = h
72
+ ismutating_h ? h : (y, x, d) -> y .= h (x, d)
91
73
end
92
74
F, H = getFuncTypes (f!, h!)
93
75
return NonLinModel {NT, F, H} (f!, h!, Ts, nu, nx, ny, nd)
94
76
end
95
77
96
78
function NonLinModel (
97
- f! :: Function , h! :: Function , Ts:: Real , nu:: Int , nx:: Int , ny:: Int , nd:: Int = 0
79
+ f:: Function , h:: Function , Ts:: Real , nu:: Int , nx:: Int , ny:: Int , nd:: Int = 0
98
80
)
99
- return NonLinModel {Float64} (f! , h! , Ts, nu, nx, ny, nd)
81
+ return NonLinModel {Float64} (f, h, Ts, nu, nx, ny, nd)
100
82
end
101
83
102
- getFuncTypes (f! :: F , h! :: H ) where {F<: Function , H<: Function } = F, H
84
+ getFuncTypes (f:: F , h:: H ) where {F<: Function , H<: Function } = F, H
103
85
104
86
105
87
"""
106
- validate_fcts (NT, f!, h! ) -> iscontinuous
88
+ validate_f (NT, f) -> ismutating
107
89
108
- Validate `f!` and `h!` function argument signatures and return `true` if `f!` is continuous .
90
+ Validate `f` function argument signature and return `true` if it is mutating .
109
91
"""
110
- function validate_fcts (NT, f!, h!)
111
- isdiscrete = hasmethod (f!,
112
- Tuple{Vector{NT}, Vector{NT}, Vector{NT}}
113
- )
114
- iscontinuous = hasmethod (f!,
115
- Tuple{Vector{NT}, Vector{NT}, Vector{NT}, Vector{NT}}
116
- )
117
- if ! isdiscrete && ! iscontinuous
118
- println (isdiscrete)
119
- println (iscontinuous)
120
- error (" state function has no method with type signature " *
121
- " f!(x::Vector{$(NT) }, u::Vector{$(NT) }, d::Vector{$(NT) }) or " *
122
- " f!(ẋ::Vector{$(NT) }, x::Vector{$(NT) }, u::Vector{$(NT) }, d::Vector{$(NT) })" )
92
+ function validate_f (NT, f)
93
+ ismutating = hasmethod (f, Tuple{Vector{NT}, Vector{NT}, Vector{NT}, Vector{NT}})
94
+ if ! (ismutating || hasmethod (f, Tuple{Vector{NT}, Vector{NT}, Vector{NT}}))
95
+ error (
96
+ " the state function has no method with type signature " *
97
+ " f(x::Vector{$(NT) }, u::Vector{$(NT) }, d::Vector{$(NT) }) or mutating form " *
98
+ " f!(xnext::Vector{$(NT) }, x::Vector{$(NT) }, u::Vector{$(NT) }, d::Vector{$(NT) })"
99
+ )
123
100
end
124
- hargsvalid = hasmethod (h!, Tuple{Vector{NT}, Vector{NT}, Vector{NT}})
125
- if ! hargsvalid
126
- error (" output function has no method with type signature " *
127
- " h!(y::Vector{$(NT) }, x::Vector{$(NT) }, d::Vector{$(NT) })" )
101
+ return ismutating
102
+ end
103
+
104
+ """
105
+ validate_h(NT, h) -> ismutating
106
+
107
+ Validate `h` function argument signature and return `true` if it is mutating.
108
+ """
109
+ function validate_h (NT, h)
110
+ ismutating = hasmethod (h, Tuple{Vector{NT}, Vector{NT}, Vector{NT}})
111
+ if ! (ismutating || hasmethod (h, Tuple{Vector{NT}, Vector{NT}}))
112
+ error (
113
+ " the output function has no method with type signature " *
114
+ " h(x::Vector{$(NT) }, d::Vector{$(NT) }) or mutating form " *
115
+ " h!(y::Vector{$(NT) }, x::Vector{$(NT) }, d::Vector{$(NT) })"
116
+ )
128
117
end
129
- return iscontinuous
118
+ return ismutating
130
119
end
131
120
132
121
" Do nothing if `model` is a [`NonLinModel`](@ref)."
133
122
steadystate! (:: SimModel , _ , _ ) = nothing
134
123
135
124
125
+
126
+
127
+
136
128
" Call ``\\ mathbf{f!(x, u, d)}`` with `model.f!` function for [`NonLinModel`](@ref)."
137
- f! (x , model:: NonLinModel , u, d) = model. f! (x, u, d)
129
+ f! (xnext , model:: NonLinModel , x, u, d) = model. f! (xnext, x, u, d)
138
130
139
131
" Call ``\\ mathbf{h!(y, x, d)}`` with `model.h` function for [`NonLinModel`](@ref)."
140
132
h! (y, model:: NonLinModel , x, d) = model. h! (y, x, d)
141
133
142
- typestr (model:: NonLinModel ) = " nonlinear"
134
+ typestr (model:: NonLinModel ) = " nonlinear"
135
+
0 commit comments