pypose.module.NLS¶
- class pypose.module.NLS[source]¶
Dynamics model for discrete-time non-linear system (NLS).
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
andobservation
, which are automatically called by internalforward
method. The system timestamp (starting from 0) is also self-added automatically once theforward
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
, andc2
, after calling a methodset_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 limited to the system’s 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. For more details go to
LTI()
.Example
A simple linear time-varying system, but defined via NLS. 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.NLS): ... 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 viaforward_hook
.state_transition
andobservation
still accept time for the flexiblity such as time-varying system. One can directly access the current system time via the propertysystime
.Note
To introduce noise in a model, redefine this method via subclassing. See example in
examples/module/ekf/tank_robot.py
.
- 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. IfNone
, the the most recent state is taken. Default:None
.input (
Tensor
) – The reference input to the dynamical system. IfNone
, the the most recent input is taken. Default:None
.t (
Tensor
) – The reference time step of the dynamical system. IfNone
, 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.