# pypose.module.System¶

class pypose.module.System[source]

The base class of a general discrete-time system dynamics model.

The state transision function $$\mathbf{f}$$ and observation function $$\mathbf{g}$$ are given by:

\begin{aligned} \mathbf{x}_{k+1} &= \mathbf{f}(\mathbf{x}_k, \mathbf{u}_k, t_k), \\ \mathbf{y}_{k} &= \mathbf{g}(\mathbf{x}_k, \mathbf{u}_k, t_k), \end{aligned}

where $$k$$, $$\mathbf{x}$$, $$\mathbf{u}$$, $$\mathbf{y}$$ are the time step, state(s), input(s), and observation(s), respectively.

Note

To use the class, users need to inherit this class and define methods state_transition and observation, which are automatically called by internal forward method. The system timestamp (starting from 0) is also self-added automatically once the forward method is called.

Note

This class provides automatic linearlization at a reference point $$\chi^*=(\mathbf{x}^*, \mathbf{u}^*, t^*)$$ along a trajectory. One can directly call those linearized system matrices as properties including A, B, C, D, c1, and c2, after calling a method set_refpoint.

Consider a point $$\chi=(\mathbf{x}^*+\delta\mathbf{x}, \mathbf{u}^*+\delta\mathbf{u}, t^*)$$ near $$\chi^*$$. We have

\begin{aligned} \mathbf{f}(\mathbf{x}, \mathbf{u}, t^*) &\approx \mathbf{f}(\mathbf{x}^*, \mathbf{u}^*, t^*) + \left. \frac{\partial \mathbf{f}}{\partial \mathbf{x}} \right|_{\chi^*} \delta \mathbf{x} + \left. \frac{\partial \mathbf{f}} {\partial \mathbf{u}} \right|_{\chi^*} \delta \mathbf{u} \\ &= \mathbf{f}(\mathbf{x}^*, \mathbf{u}^*, t^*) + \mathbf{A}(\mathbf{x} - \mathbf{x}^*) + \mathbf{B}(\mathbf{u}-\mathbf{u}^*) \\ &= \mathbf{A}\mathbf{x} + \mathbf{B}\mathbf{u} + \mathbf{c}_1 \end{aligned}

and

$\mathbf{g}(\mathbf{x}, \mathbf{u}, t^*) \approx \mathbf{C}\mathbf{x} \ + \mathbf{D}\mathbf{u} + \mathbf{c}_2$

The notion of linearization is slightly different from that in dynamical system theory. First, the linearization can be done for arbitrary point(s), not limit to the equilibrium point(s), and therefore the extra constant terms $$\mathbf{c}_1$$ and $$\mathbf{c}_2$$ are produced. Second, the linearized equations are represented by the full states and inputs: $$\mathbf{x}$$ and $$\mathbf{u}$$, rather than the perturbation format: $$\delta \mathbf{x}$$ and $$\delta \mathbf{u}$$ so that the model is consistent with, e.g., the LTI model and the iterative LQR solver. More details go to LTI().

Example

A simple linear time-varying system. Here we show an example for advancing one time step of the system at a given time step and computing the linearization.

>>> import math, torch
>>> import pypose as pp
...
>>> class Floquet(pp.module.System):
...     def __init__(self):
...         super().__init__()
...
...     def state_transition(self, state, input, t):
...
...         cc = (2 * math.pi * t / 100).cos()
...         ss = (2 * math.pi * t / 100).sin()
...
...         A = torch.tensor([[   1., cc/10],
...                           [cc/10,    1.]], device=t.device)
...         B = torch.tensor([[ss],
...                           [1.]], device=t.device)
...
...         return pp.bmv(A, state) + pp.bmv(B, input)
...
...     def observation(self, state, input, t):
...         return state + t
...
>>> # Start from t = 8, and advance one step to t = 9.
>>> step, current = 8, torch.tensor([1., 1.])
>>> input = torch.tensor(2 * math.pi / 50 * step).sin()
...
>>> system = Floquet().reset(t = step)
>>> next, observation = system(current, input)
>>> system.set_refpoint()
...
>>> print(next)        # Next state
>>> print(observation) # Observation
>>> print(system.A)    # Linearized state matrix
>>> print(system.B)    # Linearized input matrix
tensor([1.4944, 1.9320])
tensor([9., 9.])
tensor([[1.0000, 0.0844],
[0.0844, 1.0000]])
tensor([[0.5358],
[1.0000]])


Note

For generating one trajecotry given a series of inputs, advanced use of linearization, and more practical examples can be found at examples/module/dynamics.

property A

Linear/linearized system state matrix.

$\mathbf{A} = \left. \frac{\partial \mathbf{f}}{\partial \mathbf{x}} \right|_{\chi^*}$
property B

Linear/linearized system input matrix.

$\mathbf{B} = \left. \frac{\partial \mathbf{f}}{\partial \mathbf{u}} \right|_{\chi^*}$
property C

Linear/linearized system output matrix.

$\mathbf{C} = \left. \frac{\partial \mathbf{g}}{\partial \mathbf{x}} \right|_{\chi^*}$
property D

Linear/Linearized system observation matrix.

$\mathbf{D} = \left. \frac{\partial \mathbf{g}} {\partial \mathbf{u}} \right|_{\chi^*}$
property c1

Constant term generated by state-transition.

$\mathbf{c}_1 = \mathbf{f}(\mathbf{x}^*, \mathbf{u}^*, t^*) - \mathbf{A}\mathbf{x}^* - \mathbf{B}\mathbf{u}^*$
property c2

Constant term generated by observation.

$\mathbf{c}_2 = \mathbf{g}(\mathbf{x}^*, \mathbf{u}^*, t^*) - \mathbf{C}\mathbf{x}^* - \mathbf{D}\mathbf{u}^*$
forward(state, input)[source]

Defines the computation performed at every call that advances the system by one time step.

Note

The forward method implicitly increments the time step via forward_hook. state_transition and observation still accept time for the flexiblity such as time-varying system. One can directly access the current system time via the property systime.

Note

To introduce noise in a model, redefine this method via subclassing. See example in examples/module/ekf/tank_robot.py.

forward_hook(module, inputs, outputs)[source]

observation(state, input, t=None)[source]
Parameters
• state (Tensor) – The state of the dynamical system

• input (Tensor) – The input to the dynamical system

• t (Tensor) – The time step of the dynamical system. Default: None.

Returns

The observation of the system at the current step

Return type

Tensor

Note

The users need to define this method and can access the current system time via the property systime. Don’t introduce system transision noise in this function, as it will be used for linearizing the system automaticalluy.

set_refpoint(state=None, input=None, t=None)[source]

Function to set the reference point for linearization.

Parameters
• state (Tensor) – The reference state of the dynamical system. If None, the the most recent state is taken. Default: None.

• input (Tensor) – The reference input to the dynamical system. If None, the the most recent input is taken. Default: None.

• t (Tensor) – The reference time step of the dynamical system. If None, the the most recent timestamp is taken. Default: None.

Returns

The self module.

Warning

For nonlinear systems, the users have to call this function before getting the linearized system.

state_transition(state, input, t=None)[source]
Parameters
• state (Tensor) – The state of the dynamical system

• input (Tensor) – The input to the dynamical system

• t (Tensor) – The time step of the dynamical system. Default: None.

Returns

The state of the system at next time step

Return type

Tensor

Note

The users need to define this method and can access the current time via the property systime. Don’t introduce system transision noise in this function, as it will be used for linearizing the system automaticalluy.

property systime

System time, automatically advanced by forward_hook.