feat (sim): parameterized on the notion of state
This commit is contained in:
parent
391e350315
commit
48d6cc4ca8
7 changed files with 481 additions and 102 deletions
145
doc/hsim.tex
Normal file
145
doc/hsim.tex
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
\documentclass[a4paper]{article}
|
||||
\usepackage{fullpage}
|
||||
\usepackage{listings}
|
||||
\usepackage{xcolor}
|
||||
|
||||
\title{A formalization of a simulation engine for hybrid systems}
|
||||
\author{}
|
||||
\date{}
|
||||
|
||||
\setlength{\parindent}{0pt}
|
||||
|
||||
\lstdefinelanguage{ml}{
|
||||
basicstyle=\ttfamily,
|
||||
morekeywords=[1]{
|
||||
type, float, option, let, fun, with, if, else, then, in, as, match,
|
||||
},
|
||||
morekeywords=[2]{
|
||||
HNode, DNode, Idle, Running, Discrete, Continuous
|
||||
},
|
||||
keywordstyle=[1]{\color{blue}},
|
||||
keywordstyle=[2]{\color{red}},
|
||||
commentstyle=\itshape,
|
||||
columns=[l]fullflexible,
|
||||
sensitive=true,
|
||||
morecomment=[s]{(*}{*)},
|
||||
keepspaces=true,
|
||||
literate=
|
||||
{'a}{$\alpha$}{1}
|
||||
{'b}{$\beta$}{1}
|
||||
{'p}{$\rho$}{1}
|
||||
{'s}{$\sigma$}{1}
|
||||
{'y}{$y$}{1}
|
||||
{'yder}{$\dot{y}$}{1}
|
||||
{'zin}{$z_{in}$}{1}
|
||||
{'zout}{$z_{out}$}{1}
|
||||
{fun\ }{$\lambda$}{1}
|
||||
{->}{$\to$}{1}
|
||||
{+.}{$+$}{1}
|
||||
{-.}{$-$}{1}
|
||||
{=}{$=$}{1}
|
||||
{>=}{$\geq$}{1}
|
||||
{<=}{$\leq$}{1}
|
||||
}
|
||||
\lstnewenvironment{ml}{\lstset{language=ml}}{}
|
||||
\newcommand{\mlf}[1]{\lstinline[language=ml]{#1}}
|
||||
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
||||
A discrete synchronous function, or node, can be seen as a pair of a step and
|
||||
reset function, which operate on an inner state:
|
||||
|
||||
\begin{ml}
|
||||
type ('p, 'a, 'b) dnode =
|
||||
DNode : { s : 's;
|
||||
step : 's -> 'a -> 'b * 's;
|
||||
reset : 'p -> 's -> 's } -> ('p, 'a, 'b) dnode
|
||||
\end{ml}
|
||||
|
||||
A hybrid node is quite similar: it has an inner state, a step and a reset
|
||||
function; but the step function is decomposed into multiple distinct elements
|
||||
for the purpose of the simulation:
|
||||
|
||||
\begin{ml}
|
||||
type ('p, 'a, 'b, 'y, 'yder, 'zin, 'zout) hnode =
|
||||
HNode : { s : 's;
|
||||
step : 's -> 'a -> 'b * 's;
|
||||
fder : 's -> 'a -> 'y -> 'yder;
|
||||
fzer : 's -> 'a -> 'y -> 'zout;
|
||||
fout : 's -> 'a -> 'y -> 'b;
|
||||
reset : 'p -> 's -> 's;
|
||||
horizon : 's -> time;
|
||||
jump : 's -> bool;
|
||||
cget : 's -> 'y;
|
||||
cset : 's -> 'y -> 's;
|
||||
zset : 's -> 'zin -> 's;
|
||||
} -> ('p, 'a, 'b, 'y, 'yder, 'zin, 'zout) hnode
|
||||
\end{ml}
|
||||
|
||||
\mlf{step} and \mlf{reset} are on discrete steps, and behave in the same way as
|
||||
for a discrete node. \mlf{fder}, \mlf{fzer} and \mlf{fout} are used during
|
||||
integration phases with a solver. \mlf{fder} represents the derivative function
|
||||
in an initial value problem. \mlf{fzer} is the zero-crossing function, which
|
||||
computes the values of all zero-crossing function we wish to monitor. \mlf{fout}
|
||||
computes the output of the system at a particular instant.
|
||||
|
||||
\begin{figure}
|
||||
\begin{ml}
|
||||
let sim (HNode model) (DNode solver) =
|
||||
let s = { status = Idle; mstate = model.state; sstate = solver.state } in
|
||||
let step state input =
|
||||
match input, state.status with
|
||||
| Some i, _ ->
|
||||
let status = Running
|
||||
{ mode = Continuous; input = i; now = 0.0; stop = i.length } in
|
||||
None, { state with status }
|
||||
| None, Idle -> None, state
|
||||
| None, Running ({ mode = Discrete; _ } as r) ->
|
||||
let o, mstate = model.step state.mstate (r.input.u r.now) in
|
||||
let state =
|
||||
let h = model.horizon mstate in
|
||||
if h <= 0.0 then { state with mstate }
|
||||
else if r.now >= r.stop then s
|
||||
else if model.jump mstate then
|
||||
let y = model.cget mstate in
|
||||
let fder t = model.fder mstate (offset r.input r.now t) in
|
||||
let fzer t = model.fzer mstate (offset r.input r.now t) in
|
||||
let ivp = { fder; stop = r.stop -. r.now; init = y } in
|
||||
let zc = { yc = y; fzer } in
|
||||
let sstate = solver.reset (ivp, zc) state.sstate in
|
||||
let status = Running { r with mode = Continuous } in
|
||||
{ status; mstate; sstate }
|
||||
else { state with status = Running { r with mode = Continuous } }
|
||||
in Some { start = r.now; length = 0.0; u = fun _ -> o }, state
|
||||
| None, Running ({ mode = Continuous; _ } as r) ->
|
||||
let (h, f, z), sstate = solver.step state.sstate r.stop in
|
||||
let mstate = model.cset state.mstate (f h) in
|
||||
let now = r.input.start +. h in
|
||||
let state = match z with
|
||||
| None ->
|
||||
let status =
|
||||
if h >= r.stop then Running { r with mode = Discrete; now }
|
||||
else Running { r with now } in
|
||||
{ status; mstate; sstate }
|
||||
| Some z ->
|
||||
let status = Running { r with mode = Discrete; now } in
|
||||
{ status; mstate = model.zset mstate z; sstate } in
|
||||
let fout t =
|
||||
model.fout mstate (r.input.u (r.now +. t)) (f (r.now +. t)) in
|
||||
let out =
|
||||
{ start = r.input.start +. r.now; length = h -. r.now; u = fout } in
|
||||
Some out, state in
|
||||
let reset (m, s) { mstate; sstate; _ } =
|
||||
let mstate = model.reset m mstate in
|
||||
let sstate = solver.reset s sstate in
|
||||
{ status = Idle; mstate; sstate } in
|
||||
DNode { state = s; step; reset }
|
||||
\end{ml}
|
||||
\label{fig:ml:sim}
|
||||
\caption{Hybrid System Simulation}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\end{document}
|
||||
Loading…
Add table
Add a link
Reference in a new issue