class_docstr: Implements a Kalman filter. You are responsible for setting the
  various state variables to reasonable values; the defaults  will
  not give you a functional filter.
  
  For now the best documentation is my free book Kalman and Bayesian
  Filters in Python [2]_. The test files in this directory also give you a
  basic idea of use, albeit without much description.
  
  In brief, you will first construct this object, specifying the size of
  the state vector with dim_x and the size of the measurement vector that
  you will be using with dim_z. These are mostly used to perform size checks
  when you assign values to the various matrices. For example, if you
  specified dim_z=2 and then try to assign a 3x3 matrix to R (the
  measurement noise matrix you will get an assert exception because R
  should be 2x2. (If for whatever reason you need to alter the size of
  things midstream just use the underscore version of the matrices to
  assign directly: your_filter._R = a_3x3_matrix.)
  
  After construction the filter will have default matrices created for you,
  but you must specify the values for each. It’s usually easiest to just
  overwrite them rather than assign to each element yourself. This will be
  clearer in the example below. All are of type numpy.array.
  
  
  Examples
  --------
  
  Here is a filter that tracks position and velocity using a sensor that only
  reads position.
  
  First construct the object with the required dimensionality. Here the state
  (`dim_x`) has 2 coefficients (position and velocity), and the measurement
  (`dim_z`) has one. In FilterPy `x` is the state, `z` is the measurement.
  
  .. code::
  
      from filterpy.kalman import KalmanFilter
      f = KalmanFilter (dim_x=2, dim_z=1)
  
  
  Assign the initial value for the state (position and velocity). You can do this
  with a two dimensional array like so:
  
      .. code::
  
          f.x = np.array([[2.],    # position
                          [0.]])   # velocity
  
  or just use a one dimensional array, which I prefer doing.
  
  .. code::
  
      f.x = np.array([2., 0.])
  
  
  Define the state transition matrix:
  
      .. code::
  
          f.F = np.array([[1.,1.],
                          [0.,1.]])
  
  Define the measurement function. Here we need to convert a position-velocity
  vector into just a position vector, so we use:
  
      .. code::
  
      f.H = np.array([[1., 0.]])
  
  Define the state's covariance matrix P. 
  
  .. code::
  
      f.P = np.array([[1000.,    0.],
                      [   0., 1000.] ])
  
  Now assign the measurement noise. Here the dimension is 1x1, so I can
  use a scalar
  
  .. code::
  
      f.R = 5
  
  I could have done this instead:
  
  .. code::
  
      f.R = np.array([[5.]])
  
  Note that this must be a 2 dimensional array.
  
  Finally, I will assign the process noise. Here I will take advantage of
  another FilterPy library function:
  
  .. code::
  
      from filterpy.common import Q_discrete_white_noise
      f.Q = Q_discrete_white_noise(dim=2, dt=0.1, var=0.13)
  
  
  Now just perform the standard predict/update loop:
  
  .. code::
  
      while some_condition_is_true:
          z = get_sensor_reading()
          f.predict()
          f.update(z)
  
          do_something_with_estimate (f.x)
  
  
  **Procedural Form**
  
  This module also contains stand alone functions to perform Kalman filtering.
  Use these if you are not a fan of objects.
  
  **Example**
  
  .. code::
  
      while True:
          z, R = read_sensor()
          x, P = predict(x, P, F, Q)
          x, P = update(x, P, z, R, H)
  
  See my book Kalman and Bayesian Filters in Python [2]_.
  
  
  You will have to set the following attributes after constructing this
  object for the filter to perform properly. Please note that there are
  various checks in place to ensure that you have made everything the
  'correct' size. However, it is possible to provide incorrectly sized
  arrays such that the linear algebra can not perform an operation.
  It can also fail silently - you can end up with matrices of a size that
  allows the linear algebra to work, but are the wrong shape for the problem
  you are trying to solve.
  
  Parameters
  ----------
  dim_x : int
      Number of state variables for the Kalman filter. For example, if
      you are tracking the position and velocity of an object in two
      dimensions, dim_x would be 4.
      This is used to set the default size of P, Q, and u
  
  dim_z : int
      Number of of measurement inputs. For example, if the sensor
      provides you with position in (x,y), dim_z would be 2.
  
  dim_u : int (optional)
      size of the control input, if it is being used.
      Default value of 0 indicates it is not used.
  
  compute_log_likelihood : bool (default = True)
      Computes log likelihood by default, but this can be a slow
      computation, so if you never use it you can turn this computation
      off.
  
  Attributes
  ----------
  x : numpy.array(dim_x, 1)
      Current state estimate. Any call to update() or predict() updates
      this variable.
  
  P : numpy.array(dim_x, dim_x)
      Current state covariance matrix. Any call to update() or predict()
      updates this variable.
  
  x_prior : numpy.array(dim_x, 1)
      Prior (predicted) state estimate. The *_prior and *_post attributes
      are for convenience; they store the  prior and posterior of the
      current epoch. Read Only.
  
  P_prior : numpy.array(dim_x, dim_x)
      Prior (predicted) state covariance matrix. Read Only.
  
  x_post : numpy.array(dim_x, 1)
      Posterior (updated) state estimate. Read Only.
  
  P_post : numpy.array(dim_x, dim_x)
      Posterior (updated) state covariance matrix. Read Only.
  
  z : numpy.array
      Last measurement used in update(). Read only.
  
  R : numpy.array(dim_z, dim_z)
      Measurement noise covariance matrix. Also known as the
      observation covariance.
  
  Q : numpy.array(dim_x, dim_x)
      Process noise covariance matrix. Also known as the transition
      covariance.
  
  F : numpy.array()
      State Transition matrix. Also known as `A` in some formulation.
  
  H : numpy.array(dim_z, dim_x)
      Measurement function. Also known as the observation matrix, or as `C`.
  
  y : numpy.array
      Residual of the update step. Read only.
  
  K : numpy.array(dim_x, dim_z)
      Kalman gain of the update step. Read only.
  
  S :  numpy.array
      System uncertainty (P projected to measurement space). Read only.
  
  SI :  numpy.array
      Inverse system uncertainty. Read only.
  
  log_likelihood : float
      log-likelihood of the last measurement. Read only.
  
  likelihood : float
      likelihood of last measurement. Read only.
  
      Computed from the log-likelihood. The log-likelihood can be very
      small,  meaning a large negative value such as -28000. Taking the
      exp() of that results in 0.0, which can break typical algorithms
      which multiply by this value, so by default we always return a
      number >= sys.float_info.min.
  
  mahalanobis : float
      mahalanobis distance of the innovation. Read only.
  
  inv : function, default numpy.linalg.inv
      If you prefer another inverse function, such as the Moore-Penrose
      pseudo inverse, set it to that instead: kf.inv = np.linalg.pinv
  
      This is only used to invert self.S. If you know it is diagonal, you
      might choose to set it to filterpy.common.inv_diagonal, which is
      several times faster than numpy.linalg.inv for diagonal matrices.
  
  alpha : float
      Fading memory setting. 1.0 gives the normal Kalman filter, and
      values slightly larger than 1.0 (such as 1.02) give a fading
      memory effect - previous measurements have less influence on the
      filter's estimates. This formulation of the Fading memory filter
      (there are many) is due to Dan Simon [1]_.
  
  References
  ----------
  
  .. [1] Dan Simon. "Optimal State Estimation." John Wiley & Sons.
     p. 208-212. (2006)
  
  .. [2] Roger Labbe. "Kalman and Bayesian Filters in Python"
     https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python
docstr: Batch processes a sequences of measurements.
  
   Parameters
   ----------
  
   zs : list-like
       list of measurements at each time step `self.dt`. Missing
       measurements must be represented by `None`.
  
   Fs : None, list-like, default=None
       optional value or list of values to use for the state transition
       matrix F.
  
       If Fs is None then self.F is used for all epochs.
  
       Otherwise it must contain a list-like list of F's, one for
       each epoch.  This allows you to have varying F per epoch.
  
   Qs : None, np.array or list-like, default=None
       optional value or list of values to use for the process error
       covariance Q.
  
       If Qs is None then self.Q is used for all epochs.
  
       Otherwise it must contain a list-like list of Q's, one for
       each epoch.  This allows you to have varying Q per epoch.
  
   Hs : None, np.array or list-like, default=None
       optional list of values to use for the measurement matrix H.
  
       If Hs is None then self.H is used for all epochs.
  
       If Hs contains a single matrix, then it is used as H for all
       epochs.
  
       Otherwise it must contain a list-like list of H's, one for
       each epoch.  This allows you to have varying H per epoch.
  
   Rs : None, np.array or list-like, default=None
       optional list of values to use for the measurement error
       covariance R.
  
       If Rs is None then self.R is used for all epochs.
  
       Otherwise it must contain a list-like list of R's, one for
       each epoch.  This allows you to have varying R per epoch.
  
   Bs : None, np.array or list-like, default=None
       optional list of values to use for the control transition matrix B.
  
       If Bs is None then self.B is used for all epochs.
  
       Otherwise it must contain a list-like list of B's, one for
       each epoch.  This allows you to have varying B per epoch.
  
   us : None, np.array or list-like, default=None
       optional list of values to use for the control input vector;
  
       If us is None then None is used for all epochs (equivalent to 0,
       or no control input).
  
       Otherwise it must contain a list-like list of u's, one for
       each epoch.
  
  update_first : bool, optional, default=False
       controls whether the order of operations is update followed by
       predict, or predict followed by update. Default is predict->update.
  
   saver : filterpy.common.Saver, optional
       filterpy.common.Saver object. If provided, saver.save() will be
       called after every epoch
  
   Returns
   -------
  
   means : np.array((n,dim_x,1))
       array of the state for each time step after the update. Each entry
       is an np.array. In other words `means[k,:]` is the state at step
       `k`.
  
   covariance : np.array((n,dim_x,dim_x))
       array of the covariances for each time step after the update.
       In other words `covariance[k,:,:]` is the covariance at step `k`.
  
   means_predictions : np.array((n,dim_x,1))
       array of the state for each time step after the predictions. Each
       entry is an np.array. In other words `means[k,:]` is the state at
       step `k`.
  
   covariance_predictions : np.array((n,dim_x,dim_x))
       array of the covariances for each time step after the prediction.
       In other words `covariance[k,:,:]` is the covariance at step `k`.
  
   Examples
   --------
  
   .. code-block:: Python
  
       # this example demonstrates tracking a measurement where the time
       # between measurement varies, as stored in dts. This requires
       # that F be recomputed for each epoch. The output is then smoothed
       # with an RTS smoother.
  
       zs = [t + random.randn()*4 for t in range (40)]
       Fs = [np.array([[1., dt], [0, 1]] for dt in dts]
  
       (mu, cov, _, _) = kf.batch_filter(zs, Fs=Fs)
       (xs, Ps, Ks, Pps) = kf.rts_smoother(mu, cov, Fs=Fs)
   
code: def batch_filter(
      self,
      zs,
      Fs=None,
      Qs=None,
      Hs=None,
      Rs=None,
      Bs=None,
      us=None,
      update_first=False,
      saver=None,
  ):
      """Batch processes a sequences of measurements.
  
       Parameters
       ----------
  
       zs : list-like
           list of measurements at each time step `self.dt`. Missing
           measurements must be represented by `None`.
  
       Fs : None, list-like, default=None
           optional value or list of values to use for the state transition
           matrix F.
  
           If Fs is None then self.F is used for all epochs.
  
           Otherwise it must contain a list-like list of F's, one for
           each epoch.  This allows you to have varying F per epoch.
  
       Qs : None, np.array or list-like, default=None
           optional value or list of values to use for the process error
           covariance Q.
  
           If Qs is None then self.Q is used for all epochs.
  
           Otherwise it must contain a list-like list of Q's, one for
           each epoch.  This allows you to have varying Q per epoch.
  
       Hs : None, np.array or list-like, default=None
           optional list of values to use for the measurement matrix H.
  
           If Hs is None then self.H is used for all epochs.
  
           If Hs contains a single matrix, then it is used as H for all
           epochs.
  
           Otherwise it must contain a list-like list of H's, one for
           each epoch.  This allows you to have varying H per epoch.
  
       Rs : None, np.array or list-like, default=None
           optional list of values to use for the measurement error
           covariance R.
  
           If Rs is None then self.R is used for all epochs.
  
           Otherwise it must contain a list-like list of R's, one for
           each epoch.  This allows you to have varying R per epoch.
  
       Bs : None, np.array or list-like, default=None
           optional list of values to use for the control transition matrix B.
  
           If Bs is None then self.B is used for all epochs.
  
           Otherwise it must contain a list-like list of B's, one for
           each epoch.  This allows you to have varying B per epoch.
  
       us : None, np.array or list-like, default=None
           optional list of values to use for the control input vector;
  
           If us is None then None is used for all epochs (equivalent to 0,
           or no control input).
  
           Otherwise it must contain a list-like list of u's, one for
           each epoch.
  
      update_first : bool, optional, default=False
           controls whether the order of operations is update followed by
           predict, or predict followed by update. Default is predict->update.
  
       saver : filterpy.common.Saver, optional
           filterpy.common.Saver object. If provided, saver.save() will be
           called after every epoch
  
       Returns
       -------
  
       means : np.array((n,dim_x,1))
           array of the state for each time step after the update. Each entry
           is an np.array. In other words `means[k,:]` is the state at step
           `k`.
  
       covariance : np.array((n,dim_x,dim_x))
           array of the covariances for each time step after the update.
           In other words `covariance[k,:,:]` is the covariance at step `k`.
  
       means_predictions : np.array((n,dim_x,1))
           array of the state for each time step after the predictions. Each
           entry is an np.array. In other words `means[k,:]` is the state at
           step `k`.
  
       covariance_predictions : np.array((n,dim_x,dim_x))
           array of the covariances for each time step after the prediction.
           In other words `covariance[k,:,:]` is the covariance at step `k`.
  
       Examples
       --------
  
       .. code-block:: Python
  
           # this example demonstrates tracking a measurement where the time
           # between measurement varies, as stored in dts. This requires
           # that F be recomputed for each epoch. The output is then smoothed
           # with an RTS smoother.
  
           zs = [t + random.randn()*4 for t in range (40)]
           Fs = [np.array([[1., dt], [0, 1]] for dt in dts]
  
           (mu, cov, _, _) = kf.batch_filter(zs, Fs=Fs)
           (xs, Ps, Ks, Pps) = kf.rts_smoother(mu, cov, Fs=Fs)
      """
  
      # pylint: disable=too-many-statements
      n = np.size(zs, 0)
      if Fs is None:
          Fs = [self.F] * n
      if Qs is None:
          Qs = [self.Q] * n
      if Hs is None:
          Hs = [self.H] * n
      if Rs is None:
          Rs = [self.R] * n
      if Bs is None:
          Bs = [self.B] * n
      if us is None:
          us = [0] * n
  
      # mean estimates from Kalman Filter
      if self.x.ndim == 1:
          means = zeros((n, self.dim_x))
          means_p = zeros((n, self.dim_x))
      else:
          means = zeros((n, self.dim_x, 1))
          means_p = zeros((n, self.dim_x, 1))
  
      # state covariances from Kalman Filter
      covariances = zeros((n, self.dim_x, self.dim_x))
      covariances_p = zeros((n, self.dim_x, self.dim_x))
  
      if update_first:
          for i, (z, F, Q, H, R, B, u) in enumerate(
              zip(zs, Fs, Qs, Hs, Rs, Bs, us)
          ):
              self.update(z, R=R, H=H)
              means[i, :] = self.x
              covariances[i, :, :] = self.P
  
              self.predict(u=u, B=B, F=F, Q=Q)
              means_p[i, :] = self.x
              covariances_p[i, :, :] = self.P
  
              if saver is not None:
                  saver.save()
      else:
          for i, (z, F, Q, H, R, B, u) in enumerate(
              zip(zs, Fs, Qs, Hs, Rs, Bs, us)
          ):
              self.predict(u=u, B=B, F=F, Q=Q)
              means_p[i, :] = self.x
              covariances_p[i, :, :] = self.P
  
              self.update(z, R=R, H=H)
              means[i, :] = self.x
              covariances[i, :, :] = self.P
  
              if saver is not None:
                  saver.save()
  
      return (means, covariances, means_p, covariances_p)
  
imports: from __future__ import absolute_import, division
  from copy import deepcopy
  from math import log, exp, sqrt
  import sys
  import numpy
  from numpy import dot, zeros, eye, isscalar, shape
  import numpy.linalg
  from filterpy.stats import logpdf
  from filterpy.common import pretty_str, reshape_z
label_desc: Use image node_id 8 for calling the KalmanFilter obj's underlying member method code with example usage: obj.batch_filter(zs, Fs, Qs, Hs, Rs, Bs, us, update_first, saver) and returns: means,  covariances,  means_p,  covariances_p