is there a way with Mathematica to transform transferfunctions (Laplace) into differential equations?

Let's say I have the transfer function $\frac{Y(s)}{U(s)}=\text{Kp} \left(\frac{1}{s \text{Tn}}+1\right)$. What I want to get is $\dot{y}(t)\text{Tn}=\text{Kp}(\dot{u}(t)\text{Tn}+u(t))$.

On (I think) Nasser's page I found something I adapted:

sys = Kp (1 + 1/(Tn s))
sys = Together[sys]
rhs = Numerator[sys]
lhs = Denominator[sys]
rhs = rhs /. m_. s^n_. -> m Derivative[n][u[t]]
lhs = lhs /. m_. s^n_. -> m Derivative[n][y[t]]

eq = lhs == rhs

But this gives a wrong output for factors with $s^0$:

Input: eq

Output: Tn y[t]'==Kp (1+Tn u[t]')

Using Control`DEqns`ioEqnsForm

tfm = TransferFunctionModel[
  Array[(s + Subscript[a, ##])/(s + Subscript[b, ##]) &, {3, 2}], s]

enter image description here

res = Control`DEqns`ioEqnsForm[tfm];

The first argument has the differential equations

res[[1, 1]]

enter image description here

and the output equations

res[[1, 2]]

enter image description here

The second argument has the state variables


enter image description here

The third the input variables


enter image description here

The fourth the output variables


enter image description here

And the fifth the time variable


enter image description here

The function also works for delay systems

Control`DEqns`ioEqnsForm[TransferFunctionModel[(Exp[-s T] s)/(s + 1), s]]

enter image description here

 TransferFunctionModel[{{{Subscript[\[SystemsModelDelay], 3] - 1}}, s + 3}, s]]

enter image description here

For discrete-time systems it returns difference equations

TransferFunctionModel[(z - 0.1)/(z + 0.6), z, SamplingPeriod -> 1]]

enter image description here

Legacy answer

A solution for scalar transfer functions with delays.

The main function accepts the numerator and denominator of the transfer function.

tfmToTimeDomain[{num_, den_}, ipvar_, opvar_, s_, t_] := 
    Catch[polyToTimeDomain[den, opvar, s, t] == polyToTimeDomain[num, ipvar, s, t]]

A function to extract the numerator and denominator:

tfmToTimeDomain[tf_, rest__] := With[{tf1 = Together@tf}, 
    tfmToTimeDomain[Switch[Head@tf1, Times, {DeleteCases[tf1, Power[_, _?Negative]], 
    1/DeleteCases[tf1, Except[Power[_, _?Negative]]]} // Expand, 
    _, {Numerator@tf1, Denominator@tf1}], rest]]

Supporting functions:

polyToTimeDomain[poly_, var_, s_, t_] := With[{cl = CoefficientList[poly, s]},
    Plus @@ MapIndexed[coeffToTimeDomain[##, var, s, t] &, cl]]

coeffToTimeDomain[coeff_, {i_}, var_, s_, t_] /; FreeQ[coeff, Exp[__]] := 
    coeff Derivative[i-1][var][t]
coeffToTimeDomain[coeff_, {i_}, var_, s_, t_] := 
    coeff /. Exp[expr_] :> expToTimeDomain[expr, {i}, var, s, t]

expToTimeDomain[expr_, {i_}, var_, s_, t_] := Block[{cl}, 
     Switch[Length[cl = CoefficientList[expr, s]], 
        1, Exp[cl[[1]]] var[t], 
        2, Exp[cl[[1]]] Derivative[i - 1][var][t + cl[[2]]], 
        _, Throw[$Failed]


tfmToTimeDomain[{Kp (s Tn + 1), s Tn}, u, y, s, t]

enter image description here

tfmToTimeDomain[{Kp Exp[-s T1], s }, u, y, s, t]

enter image description here

tfmToTimeDomain[{Kp Exp[-s T1] (s Tn + 1), s Tn}, u, y, s, t]

enter image description here

The function should work for any continuous-time scalar transfer function with or without delays.

| improve this answer | |
  • $\begingroup$ Wow, with Together[] this seems to be a very short and elegant way. I'll try it with some other transfer functions. $\endgroup$ – Phab Mar 20 '14 at 8:03
  • 1
    $\begingroup$ What about transfer functions with a time delay? Like $tf=\frac {\text {Kp}~e^{-s\text {T1}}} {s}$. Any idea how to handle these? $\endgroup$ – Phab Mar 20 '14 at 10:16
  • $\begingroup$ I have updated the function to handle delays as well. The cases I have not considered are discrete-time systems and multivariable systems. $\endgroup$ – Suba Thomas Mar 20 '14 at 15:18
  • $\begingroup$ Works great! Unfortunately for me it's not possible to select numerator and denominator manually. But Numerator[]/Denominator[] treat the $e^{-s\text{Tt}}$ as Denominator. I tried to select them with %[[1]], %[[2]] ... but it does not work if i don't know how many factor are in the Numerator. $\endgroup$ – Phab Mar 21 '14 at 7:50
  • 2
    $\begingroup$ Phab, I have now added the function to extract numerators and denominators as well. Am I hand-holding too much. Hope you can take it from here. $\endgroup$ – Suba Thomas Mar 21 '14 at 15:33

Here's a step-by-step albeit long-winded approach to deconstructing and reconstructing your differential equation. While not elegant, perhaps it provides alternatives or ideas for further development.

sys = Kp (1 + 1/(Tn s))
tfm = TransferFunctionModel[{{sys}}, s]
ssm = StateSpaceModel[tfm]

Extract the elements of the StateSpaceModel (the a, b, c, and d matrices):

sseqn = Take[Flatten[ssm[[1]], 2], 2]    (*  {0, 1}  *)
outputeqn = Drop[Flatten[ssm[[1]], 2], 2]    (*  {Kp/Tn, Kp}  *)

Construct the state-space equation:

xaccent = sseqn.{x[t], u[t]}    (*  u[t]  *)

and the output equation:

yaccent = outputeqn.{x[t], u[t]}    (*  Kp u[t] + (Kp x[t])/Tn  *)

Now in the output equation, substitute for the x[t] with the integral of the state-space equation:

yaccent /. x[t] -> Integrate[xaccent, t]

Then differentiate that w.r.t. t and set it equal to y'[t]:

D[%, t]
eqFinal = % == y'[t]

which gives:

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.