@@ -23,9 +23,9 @@ struct NonLinModel{NT<:Real, F<:Function, H<:Function} <: SimModel{NT}
2323end
2424
2525@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)
2727
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`.
2929
3030The state update ``\m athbf{f}`` and output ``\m athbf{h}`` functions are defined as :
3131```math
@@ -45,7 +45,7 @@ Nonlinear continuous-time state-space functions are not supported for now. In su
4545manually call a differential equation solver in `f` (see [Manual](@ref man_nonlin)).
4646
4747!!! 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),
4949 [`ExtendedKalmanFilter`](@ref), [`MovingHorizonEstimator`](@ref) and [`linearize`](@ref).
5050
5151See also [`LinModel`](@ref).
@@ -61,82 +61,75 @@ Discrete-time nonlinear model with a sample time Ts = 10.0 s and:
6161```
6262"""
6363function 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
6565) 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)
9173 end
9274 F, H = getFuncTypes (f!, h!)
9375 return NonLinModel {NT, F, H} (f!, h!, Ts, nu, nx, ny, nd)
9476end
9577
9678function 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
9880)
99- return NonLinModel {Float64} (f! , h! , Ts, nu, nx, ny, nd)
81+ return NonLinModel {Float64} (f, h, Ts, nu, nx, ny, nd)
10082end
10183
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
10385
10486
10587"""
106- validate_fcts (NT, f!, h! ) -> iscontinuous
88+ validate_f (NT, f) -> ismutating
10789
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 .
10991"""
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+ )
123100 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+ )
128117 end
129- return iscontinuous
118+ return ismutating
130119end
131120
132121" Do nothing if `model` is a [`NonLinModel`](@ref)."
133122steadystate! (:: SimModel , _ , _ ) = nothing
134123
135124
125+
126+
127+
136128" 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)
138130
139131" Call ``\\ mathbf{h!(y, x, d)}`` with `model.h` function for [`NonLinModel`](@ref)."
140132h! (y, model:: NonLinModel , x, d) = model. h! (y, x, d)
141133
142- typestr (model:: NonLinModel ) = " nonlinear"
134+ typestr (model:: NonLinModel ) = " nonlinear"
135+
0 commit comments