diff --git a/README.md b/README.md index 62d4a0ef..209bd44c 100755 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Among other things, this project also does not provide methods for trajectory op # Installation -See the [documentation](https://cloctools.github.io/docs/getting-started). +See the [documentation](https://cloctools.github.io/lds-ctrl-est/docs/getting-started/getting-started/). # Reporting Issues If you encounter bugs when using this library or have specific feature requests that you believe fall within the stated scope of this project, please [open an issue on GitHub](https://github.com/cloctools/lds-ctrl-est/issues) and use an appropriate issue template where possible. You may also fork the repository and submit pull-requests with your suggested changes. diff --git a/docs/404.html b/docs/404.html index c2a01508..7ccad145 100644 --- a/docs/404.html +++ b/docs/404.html @@ -5,17 +5,17 @@ - - - - - + + + + + 404 Page not found | LDS C&E - + + + + + + +
+ + +
+
+ +
+ + + lds::Controller + + +
+ + + + + + +
+ + + +

+ lds::Controller + # +

+

More…

+

Inherited by lds::SwitchedController< System >, lds::gaussian::Controller, lds::poisson::Controller

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Controller() =default
Constructs a new Controller.
Controller(const System & sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller.
Controller(System && sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller by moving the system object.
const Vector &Control(const Vector & z, bool do_control =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal (single-step)
const Vector &ControlOutputReference(const Vector & z, bool do_control =true, bool do_estimation =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal, given previously-set (single-step)
const System &sys() const
const Matrix &Kc() const
Get state feedback controller gain.
const Matrix &Kc_inty() const
Get integral controller gain.
const Matrix &Kc_u() const
Get input feedback controller gain.
const Vector &g_design() const
Get input gain used in controller design.
const Vector &u_ref() const
Get reference input.
const Vector &x_ref() const
Get reference state.
const Vector &y_ref() const
Get reference output.
size_tcontrol_type() const
Get controller type.
data_ttau_awu() const
Get time constant of anti-integral-windup.
data_tu_lb() const
Get control lower bound.
data_tu_ub() const
Get control upper bound.
voidset_sys(const System & sys)
Set system.
voidset_g_design(const Vector & g_design)
Set input gain used in controller design (g_design)
voidset_u_ref(const Vector & u_ref)
Set reference input (u_ref)
voidset_x_ref(const Vector & x_ref)
Set reference state (x_ref)
virtual voidset_y_ref(const Vector & y_ref)
Set reference output (y_ref)
voidset_Kc(const Matrix & Kc)
Set state controller gain.
voidset_Kc_inty(const Matrix & Kc_inty)
Set integral controller gain.
voidset_Kc_u(const Matrix & Kc_u)
Set input controller gain.
voidset_tau_awu(data_t tau)
Set time constant of anti-integral-windup.
voidset_control_type(size_t control_type)
Sets the control type.
voidset_u_lb(data_t u_lb)
sets control lower bound
voidset_u_ub(data_t u_ub)
Sets control upper bound.
voidReset()
reset system and control variables.
voidPrint()
prints variables to stdout
+

+ Protected Attributes + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Systemsys_
underlying LDS
Vectoru_
control signal
Vectoru_return_
control signal that is returned to user
Vectorg_design_
input gain of the system used for controller design
Vectoru_ref_
reference input
Vectoru_ref_prev_
reference input at previous time step
Vectorx_ref_
reference state
Vectory_ref_
reference output
Vectorcx_ref_
MatrixKc_
state controller gain
MatrixKc_u_
input controller gain (optional when control updates \deltaU)
MatrixKc_inty_
integral controller gain
Vectordu_ref_
Vectordv_ref_
Vectorv_ref_
Vectordv_
Vectorv_
Control after g inversion (e.g., control in physical units)
Vectorint_e_
integrated error
Vectorint_e_awu_adjust_
anti-windup adjustment to intE
Vectoru_sat_
control signal after saturation (for antiWindup)
booldo_control_prev_
booldo_lock_control_prev_
boolu_saturated_
whether control signal has reached saturation limits
data_tu_lb_
lower bound on control
data_tu_ub_
upper bound on control
data_ttau_awu_
antiwindup time constant
data_tk_awu_
data_tt_since_control_onset_
time since control epoch onset
size_tcontrol_type_
controller type
+

+ Detailed Description + # +

+
template <typename System >
+class lds::Controller;
+

+
+

+ Public Function Details + # +

+

+ Controller + # +

+
Controller() =default
+

+

+ Controller + # +

+
inline Controller(
+    const System & sys,
+    data_t u_lb,
+    data_t u_ub,
+    size_t control_type =0
+)
+

Parameters:

+
    +
  • sys System (derived from lds::System)
  • +
  • u_lb lower bound on control (u)
  • +
  • u_ub upper bound on control (u)
  • +
  • control_type [optional] control type bit mask
  • +
+

Template Parameters:

+ +
+

+ Controller + # +

+
inline Controller(
+    System && sys,
+    data_t u_lb,
+    data_t u_ub,
+    size_t control_type =0
+)
+

Parameters:

+
    +
  • sys System (derived from lds::System)
  • +
  • u_lb lower bound on control (u)
  • +
  • u_ub upper bound on control (u)
  • +
  • control_type [optional] control type bit mask
  • +
+

Template Parameters:

+ +
+

+ Control + # +

+
inline const Vector & Control(
+    const Vector & z,
+    bool do_control =true,
+    bool do_lock_control =false,
+    data_t sigma_soft_start =0,
+    data_t sigma_u_noise =0,
+    bool do_reset_at_control_onset =true
+)
+

Parameters:

+
    +
  • z measurement
  • +
  • do_control [optional] whether to update control (true) or simply feed through u_ref (false)
  • +
  • do_lock_control [optional] whether to lock control at its current value
  • +
  • sigma_soft_start [optional] standard deviation (sigma) of a Gaussian soft-start to control (do_control from false to true)
  • +
  • sigma_u_noise [optional] standard deviation (sigma) of Gaussian noise added on top of control signal
  • +
  • do_reset_at_control_onset [optional] whether to reset controller at control epoch onset (i.e., do_control from false to true)
  • +
+

Return: updated control signal

+

Updates the control signal (single-step). This is the most flexible option, but requires user to have set the controller’s y_ref, x_ref, and u_ref variables.

+
+

+ ControlOutputReference + # +

+
inline const Vector & ControlOutputReference(
+    const Vector & z,
+    bool do_control =true,
+    bool do_estimation =true,
+    bool do_lock_control =false,
+    data_t sigma_soft_start =0,
+    data_t sigma_u_noise =0,
+    bool do_reset_at_control_onset =true
+)
+

Parameters:

+
    +
  • z measurement
  • +
  • do_control [optional] whether to update control (true) or simply feed through u_ref (false)
  • +
  • do_estimation [optional] whether to update state estimate (if false, effectively open-loop control)
  • +
  • do_lock_control [optional] whether to lock control at its current value
  • +
  • sigma_soft_start [optional] standard deviation (sigma) of a Gaussian soft-start to control (do_control from false to true)
  • +
  • sigma_u_noise [optional] standard deviation (sigma) of Gaussian noise added on top of control signal
  • +
  • do_reset_at_control_onset [optional] whether to reset controller at control epoch onset (i.e., do_control from false to true)
  • +
+

Return: updated control signal

+

Updates the control signal (single-step), given previously-set y_ref. This method calculates the rest of the set point (u_ref, x_ref) that is required to for the system to be at y_ref at steady state. This is accomplished by linearly-constrained least-squares. For a single-output system, the solution should be exact within control saturation limits. For a multi-output system, it provides the least-squares comprimise across the outputs.

+
+

+ sys + # +

+
inline const System & sys() const
+

+

+ Kc + # +

+
inline const Matrix & Kc() const
+

+

+ Kc_inty + # +

+
inline const Matrix & Kc_inty() const
+

+

+ Kc_u + # +

+
inline const Matrix & Kc_u() const
+

+

+ g_design + # +

+
inline const Vector & g_design() const
+

+

+ u_ref + # +

+
inline const Vector & u_ref() const
+

+

+ x_ref + # +

+
inline const Vector & x_ref() const
+

+

+ y_ref + # +

+
inline const Vector & y_ref() const
+

+

+ control_type + # +

+
inline size_t control_type() const
+

+

+ tau_awu + # +

+
inline data_t tau_awu() const
+

+

+ u_lb + # +

+
inline data_t u_lb() const
+

+

+ u_ub + # +

+
inline data_t u_ub() const
+

+

+ set_sys + # +

+
inline void set_sys(
+    const System & sys
+)
+

+

+ set_g_design + # +

+
inline void set_g_design(
+    const Vector & g_design
+)
+

+

+ set_u_ref + # +

+
inline void set_u_ref(
+    const Vector & u_ref
+)
+

+

+ set_x_ref + # +

+
inline void set_x_ref(
+    const Vector & x_ref
+)
+

+

+ set_y_ref + # +

+
inline virtual void set_y_ref(
+    const Vector & y_ref
+)
+

Reimplemented by: lds::gaussian::Controller::set_y_ref, lds::gaussian::SwitchedController::set_y_ref, lds::poisson::Controller::set_y_ref, lds::poisson::SwitchedController::set_y_ref

+
+

+ set_Kc + # +

+
inline void set_Kc(
+    const Matrix & Kc
+)
+

+

+ set_Kc_inty + # +

+
inline void set_Kc_inty(
+    const Matrix & Kc_inty
+)
+

+

+ set_Kc_u + # +

+
inline void set_Kc_u(
+    const Matrix & Kc_u
+)
+

+

+ set_tau_awu + # +

+
inline void set_tau_awu(
+    data_t tau
+)
+

+

+ set_control_type + # +

+
inline void set_control_type(
+    size_t control_type
+)
+

Parameters:

+
    +
  • control_type control type bit mask
  • +
+

Template Parameters:

+ +
+

+ set_u_lb + # +

+
inline void set_u_lb(
+    data_t u_lb
+)
+

Parameters:

+
    +
  • u_lb control lower bound
  • +
+
+

+ set_u_ub + # +

+
inline void set_u_ub(
+    data_t u_ub
+)
+

Parameters:

+
    +
  • u_ub control upper bound
  • +
+
+

+ Reset + # +

+
inline void Reset()
+

+

+ Print + # +

+
inline void Print()
+

+

+ Protected Attribute Details + # +

+

+ sys_ + # +

+
System sys_;
+

+

+ u_ + # +

+
Vector u_;
+

+

+ u_return_ + # +

+
Vector u_return_;
+

+

+ g_design_ + # +

+
Vector g_design_;
+

+

+ u_ref_ + # +

+
Vector u_ref_;
+

+

+ u_ref_prev_ + # +

+
Vector u_ref_prev_;
+

+

+ x_ref_ + # +

+
Vector x_ref_;
+

+

+ y_ref_ + # +

+
Vector y_ref_;
+

+

+ cx_ref_ + # +

+
Vector cx_ref_;
+

+

+ Kc_ + # +

+
Matrix Kc_;
+

+

+ Kc_u_ + # +

+
Matrix Kc_u_;
+

+

+ Kc_inty_ + # +

+
Matrix Kc_inty_;
+

+

+ du_ref_ + # +

+
Vector du_ref_;
+

+

+ dv_ref_ + # +

+
Vector dv_ref_;
+

+

+ v_ref_ + # +

+
Vector v_ref_;
+

+

+ dv_ + # +

+
Vector dv_;
+

+

+ v_ + # +

+
Vector v_;
+

+

+ int_e_ + # +

+
Vector int_e_;
+

+

+ int_e_awu_adjust_ + # +

+
Vector int_e_awu_adjust_;
+

+

+ u_sat_ + # +

+
Vector u_sat_;
+

+

+ do_control_prev_ + # +

+
bool do_control_prev_ = false;
+

+

+ do_lock_control_prev_ + # +

+
bool do_lock_control_prev_ = false;
+

+

+ u_saturated_ + # +

+
bool u_saturated_ =
+      false;
+

+

+ u_lb_ + # +

+
data_t u_lb_ {};
+

+

+ u_ub_ + # +

+
data_t u_ub_ {};
+

+

+ tau_awu_ + # +

+
data_t tau_awu_ {};
+

+

+ k_awu_ + # +

+
data_t k_awu_ = 0;
+

+

+ t_since_control_onset_ + # +

+
data_t t_since_control_onset_ = 0;
+

+

+ control_type_ + # +

+
size_t control_type_ {};
+

+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1_e_m/index.html b/docs/docs/api/classes/classlds_1_1_e_m/index.html new file mode 100644 index 00000000..5fc3e4b4 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1_e_m/index.html @@ -0,0 +1,1229 @@ + + + + + + + + + + + + + +lds::EM | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::EM + + +
+ + + + + + +
+ + + +

+ lds::EM + # +

+

More…

+

Inherited by lds::gaussian::FitEM, lds::poisson::FitEM

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
EM() =default
Constructs a new EMFit type.
EM(size_t n_x, data_t dt, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train)
Constructs a new EMFit type.
EM(const Fit & fit0, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train)
Constructs a new EMFit type.
virtual~EM() =default
const Fit &Run(bool calc_dynamics =true, bool calc_Q =true, bool calc_init =true, bool calc_output =true, bool calc_measurement =true, size_t max_iter =100, data_t tol =1e-2)
Runs fitting by Expectation(E)-Maximization(M)
std::tuple< UniformMatrixList< kMatFreeDim2 >, UniformMatrixList< kMatFreeDim2 > >ReturnData()
Returns the input/output data to caller.
const std::vector< Matrix > &x() const
gets estimated state (over time)
const std::vector< Matrix > &y() const
gets estimated output (over time)
const Matrix &sum_E_x_t_x_t() const
gets state-input covariance
const Matrix &sum_E_xu_tm1_xu_tm1() const
gets state-input covariance (t-minus-1)
const Matrix &sum_E_xu_t_xu_tm1() const
gets single lag state-input covariance
size_tn_t_tot()
total number of time samples
const Vector &theta() const
gets parameters updated in M step
+

+ Protected Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
voidExpectation(bool force_common_initial =false)
Expectation step.
voidMaximization(bool calc_dynamics =true, bool calc_Q =true, bool calc_init =false, bool calc_output =false, bool calc_measurement =false)
Maximization step.
voidMaximizeDynamics()
voidMaximizeQ()
voidMaximizeInitial()
virtual voidMaximizeOutput() =0
virtual voidMaximizeMeasurement() =0
voidSmooth(bool force_common_initial)
get smoothed estimates
virtual voidRecurseKe(Matrix & Ke, Cube & P_pre, Cube & P_post, size_t t) =0
recursively update estimator gain Ke
voidReset()
reset to initial conditions
voidInitVars()
Initializes the variables.
VectorUpdateTheta()
updates parameter list, theta
+

+ Protected Attributes + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformMatrixList< kMatFreeDim2 >u_
input training data
UniformMatrixList< kMatFreeDim2 >z_
measurement training data
std::vector< Matrix >x_
state estimate
std::vector< Cube >P_
state estimate cov
std::vector< Cube >P_t_tm1_
single-lag state covariance
std::vector< Matrix >y_
output estimate
Matrixdiag_y_
Matrixsum_E_x_t_x_t_
state covariance (current time)
Matrixsum_E_xu_tm1_xu_tm1_
state-input covariance (t-minus-1)
Matrixsum_E_xu_t_xu_tm1_
single lag state-input covariance
Fitfit_
Vectortheta_
data_tdt_
sample period
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
size_tn_trials_
number of input/output data sequences
std::vector< size_t >n_t_
number of time steps
size_tn_t_tot_
total number of time steps across trials
+

+ Detailed Description + # +

+
template <typename Fit >
+class lds::EM;
+

+
+

+ Public Function Details + # +

+

+ EM + # +

+
EM() =default
+

+

+ EM + # +

+
EM(
+    size_t n_x,
+    data_t dt,
+    UniformMatrixList< kMatFreeDim2 > && u_train,
+    UniformMatrixList< kMatFreeDim2 > && z_train
+)
+

Parameters:

+
    +
  • n_x number of states
  • +
  • dt sample period
  • +
  • u_train input training data
  • +
  • z_train measurement training data
  • +
+
+

+ EM + # +

+
EM(
+    const Fit & fit0,
+    UniformMatrixList< kMatFreeDim2 > && u_train,
+    UniformMatrixList< kMatFreeDim2 > && z_train
+)
+

Parameters:

+
    +
  • fit0 initial fit
  • +
  • u_train input training data
  • +
  • z_train measurement training data
  • +
+
+

+ ~EM + # +

+
virtual ~EM() =default
+

+

+ Run + # +

+
const Fit & Run(
+    bool calc_dynamics =true,
+    bool calc_Q =true,
+    bool calc_init =true,
+    bool calc_output =true,
+    bool calc_measurement =true,
+    size_t max_iter =100,
+    data_t tol =1e-2
+)
+

Parameters:

+
    +
  • calc_dynamics [optional] whether to calculate dynamics (A, B)
  • +
  • calc_Q [optional] whether to calculate process noise covariance
  • +
  • calc_init [optional] whether to calculate initial conditions
  • +
  • calc_output [optional] whether to calculate output function
  • +
  • calc_measurement [optional] whether to calculate parameters for measurement/observation law
  • +
  • max_iter max number of iterations
  • +
  • tol convergence tolerance (max fractional abs change)
  • +
+

Return: Fit

+
+

+ ReturnData + # +

+
inline std::tuple< UniformMatrixList< kMatFreeDim2 >, UniformMatrixList< kMatFreeDim2 > > ReturnData()
+

Return: tuple(input data, output data)

+
+

+ x + # +

+
inline const std::vector< Matrix > & x() const
+

+

+ y + # +

+
inline const std::vector< Matrix > & y() const
+

+

+ sum_E_x_t_x_t + # +

+
inline const Matrix & sum_E_x_t_x_t() const
+

+

+ sum_E_xu_tm1_xu_tm1 + # +

+
inline const Matrix & sum_E_xu_tm1_xu_tm1() const
+

+

+ sum_E_xu_t_xu_tm1 + # +

+
inline const Matrix & sum_E_xu_t_xu_tm1() const
+

+

+ n_t_tot + # +

+
inline size_t n_t_tot()
+

+

+ theta + # +

+
inline const Vector & theta() const
+

+

+ Protected Function Details + # +

+

+ Expectation + # +

+
void Expectation(
+    bool force_common_initial =false
+)
+

Parameters:

+
    +
  • force_common_initial whether to force common initial condition for all trials
  • +
+
+

+ Maximization + # +

+
void Maximization(
+    bool calc_dynamics =true,
+    bool calc_Q =true,
+    bool calc_init =false,
+    bool calc_output =false,
+    bool calc_measurement =false
+)
+

Parameters:

+
    +
  • calc_dynamics [optional] whether to caclulate dynamics (A, B)
  • +
  • calc_Q [optional] whether to calculate process noise covariance
  • +
  • calc_init [optional] whether to calculate initial conditions
  • +
  • calc_output [optional] whether to calculate output function
  • +
  • calc_measurement [optional] whether to calculate parameters for measurement/observation law
  • +
+
+

+ MaximizeDynamics + # +

+
void MaximizeDynamics()
+

+

+ MaximizeQ + # +

+
void MaximizeQ()
+

+

+ MaximizeInitial + # +

+
void MaximizeInitial()
+

+

+ MaximizeOutput + # +

+
virtual void MaximizeOutput() =0
+

Reimplemented by: lds::gaussian::FitEM::MaximizeOutput, lds::poisson::FitEM::MaximizeOutput

+
+

+ MaximizeMeasurement + # +

+
virtual void MaximizeMeasurement() =0
+

Reimplemented by: lds::gaussian::FitEM::MaximizeMeasurement, lds::poisson::FitEM::MaximizeMeasurement

+
+

+ Smooth + # +

+
void Smooth(
+    bool force_common_initial
+)
+

Parameters:

+
    +
  • force_common_initial whether to force common initial conditions
  • +
+
+

+ RecurseKe + # +

+
virtual void RecurseKe(
+    Matrix & Ke,
+    Cube & P_pre,
+    Cube & P_post,
+    size_t t
+) =0
+

Parameters:

+
    +
  • Ke estimator gain
  • +
  • P_pre cov of predicted state est.
  • +
  • P_post cov of postior sate est.
  • +
  • t time
  • +
+

Reimplemented by: lds::gaussian::FitEM::RecurseKe, lds::poisson::FitEM::RecurseKe

+
+

+ Reset + # +

+
void Reset()
+

+

+ InitVars + # +

+
void InitVars()
+

+

+ UpdateTheta + # +

+
Vector UpdateTheta()
+

Return: parameter list

+
+

+ Protected Attribute Details + # +

+

+ u_ + # +

+
UniformMatrixList< kMatFreeDim2 > u_;
+

+

+ z_ + # +

+
UniformMatrixList< kMatFreeDim2 > z_;
+

+

+ x_ + # +

+
std::vector< Matrix > x_;
+

+

+ P_ + # +

+
std::vector< Cube > P_;
+

+

+ P_t_tm1_ + # +

+
std::vector< Cube > P_t_tm1_;
+

+

+ y_ + # +

+
std::vector< Matrix > y_;
+

+

+ diag_y_ + # +

+
Matrix diag_y_;
+

+

+ sum_E_x_t_x_t_ + # +

+
Matrix sum_E_x_t_x_t_;
+

+

+ sum_E_xu_tm1_xu_tm1_ + # +

+
Matrix sum_E_xu_tm1_xu_tm1_;
+

+

+ sum_E_xu_t_xu_tm1_ + # +

+
Matrix sum_E_xu_t_xu_tm1_;
+

+

+ fit_ + # +

+
Fit fit_;
+

+

+ theta_ + # +

+
Vector theta_;
+

+

+ dt_ + # +

+
data_t dt_ {};
+

+

+ n_u_ + # +

+
size_t n_u_ {};
+

+

+ n_x_ + # +

+
size_t n_x_ {};
+

+

+ n_y_ + # +

+
size_t n_y_ {};
+

+

+ n_trials_ + # +

+
size_t n_trials_ {};
+

+

+ n_t_ + # +

+
std::vector< size_t > n_t_;
+

+

+ n_t_tot_ + # +

+
size_t n_t_tot_ {};
+

+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1_fit/index.html b/docs/docs/api/classes/classlds_1_1_fit/index.html new file mode 100644 index 00000000..72b86e6a --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1_fit/index.html @@ -0,0 +1,907 @@ + + + + + + + + + + + + + +lds::Fit | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::Fit + + +
+ + + + + + +
+ + + +

+ lds::Fit + # +

+

LDS Fit Type. +
#include <lds_fit.h>

+

Inherited by lds::gaussian::Fit, lds::poisson::Fit

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Fit() =default
Constructs a new Fit.
Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt)
Constructs a new Fit.
virtual~Fit() =default
size_tn_u() const
gets number of inputs
size_tn_x() const
gets number of states
size_tn_y() const
gets number of outputs
data_tdt() const
gets sample period
const Matrix &A() const
gets state matrix
const Matrix &B() const
gets input matrix
const Vector &g() const
gets input gain
const Vector &m() const
gets process disturbance
const Matrix &Q() const
gets process noise covariance
const Vector &x0() const
gets initial state estimate
const Matrix &P0() const
gets covariance of initial state estimate
const Matrix &C() const
gets output matrix
const Vector &d() const
gets output bias
virtual const Matrix &R() const =0
voidset_A(const Matrix & A)
sets state matrix
voidset_B(const Matrix & B)
sets input matrix
voidset_g(const Vector & g)
sets input gain/conversion factor
voidset_m(const Vector & m)
sets process disturbance
voidset_Q(const Matrix & Q)
sets process noise covariance
virtual voidset_R(const Matrix & R) =0
sets output noise covariance (if any)
voidset_x0(const Vector & x0)
sets initial state estimate
voidset_P0(const Matrix & P0)
sets initial state estimate covariance
voidset_C(const Matrix & C)
sets output matrix
voidset_d(const Vector & d)
sets output bias
Viewf(Matrix & x, const Matrix & u, size_t t)
system dynamics function
Viewf(Matrix & x_pre, const Matrix & x_post, const Matrix & u, size_t t)
system dynamics function
virtual Viewh(Matrix & y, const Matrix & x, size_t t) =0
output function
+

+ Protected Attributes + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
data_tdt_
sample period
MatrixA_
state matrix
MatrixB_
input matrix
Vectorg_
input gain
Vectorm_
process noise mean
MatrixQ_
process noise cov
MatrixC_
output matrix
Vectord_
output bias
MatrixR_
measurement noise
Vectorx0_
initial state
MatrixP0_
initial covar
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
+
+
+

+ Public Function Details + # +

+

+ Fit + # +

+
Fit() =default
+

+

+ Fit + # +

+
Fit(
+    size_t n_u,
+    size_t n_x,
+    size_t n_y,
+    data_t dt
+)
+

Parameters:

+
    +
  • n_u number of inputs
  • +
  • n_x number of states
  • +
  • n_y number of outputs
  • +
  • dt sample period
  • +
+
+

+ ~Fit + # +

+
virtual ~Fit() =default
+

+

+ n_u + # +

+
inline size_t n_u() const
+

+

+ n_x + # +

+
inline size_t n_x() const
+

+

+ n_y + # +

+
inline size_t n_y() const
+

+

+ dt + # +

+
inline data_t dt() const
+

+

+ A + # +

+
inline const Matrix & A() const
+

+

+ B + # +

+
inline const Matrix & B() const
+

+

+ g + # +

+
inline const Vector & g() const
+

+

+ m + # +

+
inline const Vector & m() const
+

+

+ Q + # +

+
inline const Matrix & Q() const
+

+

+ x0 + # +

+
inline const Vector & x0() const
+

+

+ P0 + # +

+
inline const Matrix & P0() const
+

+

+ C + # +

+
inline const Matrix & C() const
+

+

+ d + # +

+
inline const Vector & d() const
+

+

+ R + # +

+
virtual const Matrix & R() const =0
+

Reimplemented by: lds::gaussian::Fit::R, lds::poisson::Fit::R

+
+

+ set_A + # +

+
inline void set_A(
+    const Matrix & A
+)
+

+

+ set_B + # +

+
inline void set_B(
+    const Matrix & B
+)
+

+

+ set_g + # +

+
inline void set_g(
+    const Vector & g
+)
+

+

+ set_m + # +

+
inline void set_m(
+    const Vector & m
+)
+

+

+ set_Q + # +

+
inline void set_Q(
+    const Matrix & Q
+)
+

+

+ set_R + # +

+
virtual void set_R(
+    const Matrix & R
+) =0
+

Reimplemented by: lds::gaussian::Fit::set_R, lds::poisson::Fit::set_R

+
+

+ set_x0 + # +

+
inline void set_x0(
+    const Vector & x0
+)
+

+

+ set_P0 + # +

+
inline void set_P0(
+    const Matrix & P0
+)
+

+

+ set_C + # +

+
inline void set_C(
+    const Matrix & C
+)
+

+

+ set_d + # +

+
inline void set_d(
+    const Vector & d
+)
+

+

+ f + # +

+
inline View f(
+    Matrix & x,
+    const Matrix & u,
+    size_t t
+)
+

Parameters:

+
    +
  • x state estimate (over time)
  • +
  • u input (over time)
  • +
  • t time index
  • +
+

Return: view of updated state

+
+

+ f + # +

+
inline View f(
+    Matrix & x_pre,
+    const Matrix & x_post,
+    const Matrix & u,
+    size_t t
+)
+

Parameters:

+
    +
  • x_pre predicted state est.
  • +
  • x_post posterior state est.
  • +
  • u input (over time)
  • +
  • t time index
  • +
+

Return: view of predicted state

+
+

+ h + # +

+
virtual View h(
+    Matrix & y,
+    const Matrix & x,
+    size_t t
+) =0
+

Parameters:

+
    +
  • y output estimate (over time)
  • +
  • x state estimate (over time)
  • +
  • t time index
  • +
+

Return: output

+

Reimplemented by: lds::gaussian::Fit::h, lds::poisson::Fit::h

+
+

+ Protected Attribute Details + # +

+

+ dt_ + # +

+
data_t dt_ {};
+

+

+ A_ + # +

+
Matrix A_;
+

+

+ B_ + # +

+
Matrix B_;
+

+

+ g_ + # +

+
Vector g_;
+

+

+ m_ + # +

+
Vector m_;
+

+

+ Q_ + # +

+
Matrix Q_;
+

+

+ C_ + # +

+
Matrix C_;
+

+

+ d_ + # +

+
Vector d_;
+

+

+ R_ + # +

+
Matrix R_;
+

+

+ x0_ + # +

+
Vector x0_;
+

+

+ P0_ + # +

+
Matrix P0_;
+

+

+ n_u_ + # +

+
size_t n_u_ {};
+

+

+ n_x_ + # +

+
size_t n_x_ {};
+

+

+ n_y_ + # +

+
size_t n_y_ {};
+

+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1_s_s_i_d/index.html b/docs/docs/api/classes/classlds_1_1_s_s_i_d/index.html new file mode 100644 index 00000000..8650f759 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1_s_s_i_d/index.html @@ -0,0 +1,896 @@ + + + + + + + + + + + + + +lds::SSID | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::SSID + + +
+ + + + + + +
+ + + +

+ lds::SSID + # +

+

More…

+

Inherited by lds::gaussian::FitSSID, lds::poisson::FitSSID

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Name
SSID() =default
Constructs a new SSIDFit type.
SSID(size_t n_x, size_t n_h, data_t dt, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train, const Vector & d =Vector(1).fill(-kInf))
Constructs a new SSIDFit type.
std::tuple< Fit, Vector >Run(SSIDWt ssid_wt)
Runs fitting by subspace identification (SSID)
std::tuple< UniformMatrixList< kMatFreeDim2 >, UniformMatrixList< kMatFreeDim2 > >ReturnData()
Returns the I/O data to caller.
+

+ Protected Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
voidCalcD(data_t t_silence =0.1, data_t thresh_silence =0.001)
Using periods of silence in inputs (u), calculates the output \ bias (d)
voidCreateHankelDataMat()
Creates the block-hankel I/O data matrix.
virtual voidDecomposeData() =0
Decompose data to lower-triangular matrix (used in Solve)
voidCalcSVD(SSIDWt wt)
performs the singular value decomposition (SVD)
voidSolve(data_t wt_dc)
solves for LDS parameters
voidRecomputeExtObs()
recompute extended observability matrix from estimates of A, C
+

+ Protected Attributes + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformMatrixList< kMatFreeDim2 >u_
input training data
UniformMatrixList< kMatFreeDim2 >z_
measurement training data
MatrixD_
block-Hankel I/O data matrix
Fitfit_
fit
Matrixg_dc_
I/O gain @ DC.
data_tdt_
sample period
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
size_tn_h_
size_tn_trials_
number of input/output data sequences
std::vector< size_t >n_t_
number of time steps
size_tn_t_tot_
total number of time steps across trials
MatrixL_
lower triangle decomp of covariance matrix
Vectors_
singular values
Matrixext_obs_t_
extended observability matrix
+

+ Detailed Description + # +

+
template <typename Fit >
+class lds::SSID;
+

+
+

+ Public Function Details + # +

+

+ SSID + # +

+
SSID() =default
+

+

+ SSID + # +

+
SSID(
+    size_t n_x,
+    size_t n_h,
+    data_t dt,
+    UniformMatrixList< kMatFreeDim2 > && u_train,
+    UniformMatrixList< kMatFreeDim2 > && z_train,
+    const Vector & d =Vector(1).fill(-kInf)
+)
+

Parameters:

+
    +
  • n_x number of states
  • +
  • n_h size of block-hankel data matrix
  • +
  • dt sample period
  • +
  • u_train input training data
  • +
  • z_train measurement training data
  • +
  • d output bias
  • +
+
+

+ Run + # +

+
std::tuple< Fit, Vector > Run(
+    SSIDWt ssid_wt
+)
+

Parameters:

+
    +
  • ssid_wt weight for singular value decomp
  • +
+

Return: tuple (Fit, singular values)

+
+

+ ReturnData + # +

+
inline std::tuple< UniformMatrixList< kMatFreeDim2 >, UniformMatrixList< kMatFreeDim2 > > ReturnData()
+

Return: tuple(input data, output data)

+
+

+ Protected Function Details + # +

+

+ CalcD + # +

+
void CalcD(
+    data_t t_silence =0.1,
+    data_t thresh_silence =0.001
+)
+

Parameters:

+
    +
  • t_silence threshold on period of time that qualifies as “silence”
  • +
  • thresh_silence threshold on input amplitude u that qualifies as “silence”
  • +
+
+

+ CreateHankelDataMat + # +

+
void CreateHankelDataMat()
+

Creates the block-hankel I/O data matrix. Also calculates I/O gain @ DC.

+
+

+ DecomposeData + # +

+
virtual void DecomposeData() =0
+

Reimplemented by: lds::gaussian::FitSSID::DecomposeData, lds::poisson::FitSSID::DecomposeData

+
+

+ CalcSVD + # +

+
void CalcSVD(
+    SSIDWt wt
+)
+

Parameters:

+
    +
  • ssid_wt weight for SVD
  • +
+
+

+ Solve + # +

+
void Solve(
+    data_t wt_dc
+)
+

Parameters:

+
    +
  • wt_dc weight placed on getting correct DC I/O gain
  • +
+
+

+ RecomputeExtObs + # +

+
void RecomputeExtObs()
+

+

+ Protected Attribute Details + # +

+

+ u_ + # +

+
UniformMatrixList< kMatFreeDim2 > u_;
+

+

+ z_ + # +

+
UniformMatrixList< kMatFreeDim2 > z_;
+

+

+ D_ + # +

+
Matrix D_;
+

+

+ fit_ + # +

+
Fit fit_;
+

+

+ g_dc_ + # +

+
Matrix g_dc_;
+

+

+ dt_ + # +

+
data_t dt_ {};
+

+

+ n_u_ + # +

+
size_t n_u_ {};
+

+

+ n_x_ + # +

+
size_t n_x_ {};
+

+

+ n_y_ + # +

+
size_t n_y_ {};
+

+

+ n_h_ + # +

+
size_t n_h_ {};
+

+

+ n_trials_ + # +

+
size_t n_trials_ {};
+

+

+ n_t_ + # +

+
std::vector< size_t > n_t_;
+

+

+ n_t_tot_ + # +

+
size_t n_t_tot_ {};
+

+

+ L_ + # +

+
Matrix L_;
+

+

+ s_ + # +

+
Vector s_;
+

+

+ ext_obs_t_ + # +

+
Matrix ext_obs_t_;
+

+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1_switched_controller/index.html b/docs/docs/api/classes/classlds_1_1_switched_controller/index.html new file mode 100644 index 00000000..e4f3824e --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1_switched_controller/index.html @@ -0,0 +1,846 @@ + + + + + + + + + + + + + +lds::SwitchedController | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::SwitchedController + + +
+ + + + + + +
+ + + +

+ lds::SwitchedController + # +

+

SwitchedController Type. More…

+


#include <lds_sctrl.h>

+

Inherits from lds::Controller< System >

+

Inherited by lds::gaussian::SwitchedController, lds::poisson::SwitchedController

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
SwitchedController() =default
Constructs a new SwitchedController.
SwitchedController(const std::vector< System > & systems, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new SwitchedController.
SwitchedController(std::vector< System > && systems, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new SwitchedController (moves systems).
voidSwitch(size_t idx, bool do_force_switch =false)
Switch to a different sub-system/controller.
voidset_Kc(const UniformMatrixList<> & Kc)
sets state feedback gains
voidset_Kc(UniformMatrixList<> && Kc)
sets state feedback gains (moving)
voidset_Kc_inty(const UniformMatrixList<> & Kc_inty)
sets integral feedback gains
voidset_Kc_inty(UniformMatrixList<> && Kc_inty)
sets integral feedback gains (moving)
voidset_Kc_u(const UniformMatrixList<> & Kc_u)
sets input feedback gains
voidset_Kc_u(UniformMatrixList<> && Kc_u)
sets input feedback gains (moving)
voidset_g_design(const UniformVectorList & g)
sets input gain used during controller design
voidset_g_design(UniformVectorList && g)
sets input gain used during controller design (moving)
+

+ Protected Attributes + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
std::vector< System >systems_
underlying sub-systems which are switched between
size_tn_sys_
number of systems
size_tidx_
current system/controller index.
UniformMatrixListKc_list_
UniformMatrixListKc_inty_list_
UniformMatrixListKc_u_list_
UniformVectorListg_design_list_
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Controller() =default
Constructs a new Controller.
Controller(const System & sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller.
Controller(System && sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller by moving the system object.
const Vector &Control(const Vector & z, bool do_control =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal (single-step)
const Vector &ControlOutputReference(const Vector & z, bool do_control =true, bool do_estimation =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal, given previously-set (single-step)
const System &sys() const
const Matrix &Kc() const
Get state feedback controller gain.
const Matrix &Kc_inty() const
Get integral controller gain.
const Matrix &Kc_u() const
Get input feedback controller gain.
const Vector &g_design() const
Get input gain used in controller design.
const Vector &u_ref() const
Get reference input.
const Vector &x_ref() const
Get reference state.
const Vector &y_ref() const
Get reference output.
size_tcontrol_type() const
Get controller type.
data_ttau_awu() const
Get time constant of anti-integral-windup.
data_tu_lb() const
Get control lower bound.
data_tu_ub() const
Get control upper bound.
voidset_sys(const System & sys)
Set system.
voidset_u_ref(const Vector & u_ref)
Set reference input (u_ref)
voidset_x_ref(const Vector & x_ref)
Set reference state (x_ref)
virtual voidset_y_ref(const Vector & y_ref)
Set reference output (y_ref)
voidset_tau_awu(data_t tau)
Set time constant of anti-integral-windup.
voidset_control_type(size_t control_type)
Sets the control type.
voidset_u_lb(data_t u_lb)
sets control lower bound
voidset_u_ub(data_t u_ub)
Sets control upper bound.
voidReset()
reset system and control variables.
voidPrint()
prints variables to stdout
+

Protected Attributes inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Systemsys_
underlying LDS
Vectoru_
control signal
Vectoru_return_
control signal that is returned to user
Vectorg_design_
input gain of the system used for controller design
Vectoru_ref_
reference input
Vectoru_ref_prev_
reference input at previous time step
Vectorx_ref_
reference state
Vectory_ref_
reference output
Vectorcx_ref_
MatrixKc_
state controller gain
MatrixKc_u_
input controller gain (optional when control updates \deltaU)
MatrixKc_inty_
integral controller gain
Vectordu_ref_
Vectordv_ref_
Vectorv_ref_
Vectordv_
Vectorv_
Control after g inversion (e.g., control in physical units)
Vectorint_e_
integrated error
Vectorint_e_awu_adjust_
anti-windup adjustment to intE
Vectoru_sat_
control signal after saturation (for antiWindup)
booldo_control_prev_
booldo_lock_control_prev_
boolu_saturated_
whether control signal has reached saturation limits
data_tu_lb_
lower bound on control
data_tu_ub_
upper bound on control
data_ttau_awu_
antiwindup time constant
data_tk_awu_
data_tt_since_control_onset_
time since control epoch onset
size_tcontrol_type_
controller type
+

+ Detailed Description + # +

+
template <typename System >
+class lds::SwitchedController;
+

+
+

+ Public Function Details + # +

+

+ SwitchedController + # +

+
SwitchedController() =default
+

+

+ SwitchedController + # +

+
inline SwitchedController(
+    const std::vector< System > & systems,
+    data_t u_lb,
+    data_t u_ub,
+    size_t control_type =0
+)
+

Parameters:

+
    +
  • systems vector of sub-systems
  • +
  • u_lb lower bound on control (u)
  • +
  • u_ub upper bound on control (u)
  • +
  • control_type [optional] control type bit mask
  • +
+
+

+ SwitchedController + # +

+
inline SwitchedController(
+    std::vector< System > && systems,
+    data_t u_lb,
+    data_t u_ub,
+    size_t control_type =0
+)
+

Parameters:

+
    +
  • systems vector of sub-systems
  • +
  • u_lb lower bound on control (u)
  • +
  • u_ub upper bound on control (u)
  • +
  • control_type [optional] control type bit mask
  • +
+
+

+ Switch + # +

+
inline void Switch(
+    size_t idx,
+    bool do_force_switch =false
+)
+

Parameters:

+
    +
  • idx index
  • +
  • do_force_switch whether to force a system switch even if already there.
  • +
+
+

+ set_Kc + # +

+
inline void set_Kc(
+    const UniformMatrixList<> & Kc
+)
+

+

+ set_Kc + # +

+
inline void set_Kc(
+    UniformMatrixList<> && Kc
+)
+

+

+ set_Kc_inty + # +

+
inline void set_Kc_inty(
+    const UniformMatrixList<> & Kc_inty
+)
+

+

+ set_Kc_inty + # +

+
inline void set_Kc_inty(
+    UniformMatrixList<> && Kc_inty
+)
+

+

+ set_Kc_u + # +

+
inline void set_Kc_u(
+    const UniformMatrixList<> & Kc_u
+)
+

+

+ set_Kc_u + # +

+
inline void set_Kc_u(
+    UniformMatrixList<> && Kc_u
+)
+

+

+ set_g_design + # +

+
inline void set_g_design(
+    const UniformVectorList & g
+)
+

+

+ set_g_design + # +

+
inline void set_g_design(
+    UniformVectorList && g
+)
+

+

+ Protected Attribute Details + # +

+

+ systems_ + # +

+
std::vector< System > systems_;
+

+

+ n_sys_ + # +

+
size_t n_sys_ {};
+

+

+ idx_ + # +

+
size_t idx_ {};
+

+

+ Kc_list_ + # +

+
UniformMatrixList Kc_list_;
+

+

+ Kc_inty_list_ + # +

+
UniformMatrixList Kc_inty_list_;
+

+

+ Kc_u_list_ + # +

+
UniformMatrixList Kc_u_list_;
+

+

+ g_design_list_ + # +

+
UniformVectorList g_design_list_;
+

+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1_system/index.html b/docs/docs/api/classes/classlds_1_1_system/index.html new file mode 100644 index 00000000..a97ab114 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1_system/index.html @@ -0,0 +1,1324 @@ + + + + + + + + + + + + + +lds::System | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::System + + +
+ + + + + + +
+ + + +

+ lds::System + # +

+

Linear Dynamical System Type. +
#include <lds_sys.h>

+

Inherited by lds::gaussian::System, lds::poisson::System

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
System() =default
Constructs a new System.
System(size_t n_u, size_t n_x, size_t n_y, data_t dt, data_t p0 =kDefaultP0, data_t q0 =kDefaultQ0)
constructs a new System
virtual~System()
voidFilter(const Vector & u_tm1, const Vector & z)
Filter data to produce causal state estimates.
virtual const Vector &Simulate(const Vector & u_tm1) =0
simulates system (single time step)
voidf(const Vector & u, bool do_add_noise =false)
system dynamics function
virtual voidh() =0
system output function
virtual Vectorh_(Vector x) =0
system output function (stateless)
size_tn_u() const
Get number of inputs.
size_tn_x() const
Get number of states.
size_tn_y() const
Get number of outputs.
data_tdt() const
Get sample period.
const Vector &x() const
Get current state.
const Matrix &P() const
Get covariance of state estimate.
const Vector &m() const
Get current process disturbance/bias.
const Matrix &P_m() const
Get covariance of process disturbance estimate.
const Vector &cx() const
Get C*x.
const Vector &y() const
Get output.
const Vector &x0() const
Get initial state.
const Vector &m0() const
Get initial disturbance.
const Matrix &A() const
Get state matrix.
const Matrix &B() const
Get input matrix.
const Vector &g() const
Get input gain/conversion factor.
const Matrix &C() const
Get output matrix.
const Vector &d() const
Get output bias.
const Matrix &Ke() const
Get estimator gain.
const Matrix &Ke_m() const
Get estimator gain for process disturbance (m)
const Matrix &Q()
Get process noise covariance.
const Matrix &Q_m()
Get process noise covariance of disturbance evoluation.
const Matrix &P0()
Get covariance of initial state.
const Matrix &P0_m()
Get covariance of initial process disturbance.
voidset_A(const Matrix & A)
Set state matrix.
voidset_B(const Matrix & B)
Set input matrix.
voidset_m(const Vector & m, bool do_force_assign =false)
Set process disturbance.
voidset_g(const Vector & g)
Set input gain.
voidset_Q(const Matrix & Q)
Set process noise covariance.
voidset_Q_m(const Matrix & Q_m)
Set process noise covariance of disturbance evoluation.
voidset_x0(const Vector & x0)
Set initial state.
voidset_P0(const Matrix & P0)
Set covariance of initial state.
voidset_P0_m(const Matrix & P0_m)
Set covariance of initial process disturbance.
voidset_C(const Matrix & C)
Set output matrix.
voidset_d(const Vector & d)
Set output bias.
voidset_x(const Vector & x)
Set state of system.
voidReset()
Reset system variables.
std::vector< UniformMatrixList< kMatFreeDim2 > >nstep_pred_block(UniformMatrixList< kMatFreeDim2 > u, UniformMatrixList< kMatFreeDim2 > z, size_t n_pred =1)
voidPrint()
Print system variables to stdout.
+

+ Protected Functions + # +

+ + + + + + + + + + + + + + + + + +
Name
virtual voidRecurseKe() =0
Recursively recalculate estimator gain (Ke)
voidInitVars(data_t p0 =kDefaultP0, data_t q0 =kDefaultQ0)
+

+ Public Attributes + # +

+ + + + + + + + + + + + + +
Name
booldo_adapt_m
whether to adaptively estimate disturbance m
+

+ Protected Attributes + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
std::size_tn_x_
number of states
std::size_tn_u_
number of inputs
std::size_tn_y_
number of outputs
data_tdt_
sample period
Vectorx_
state
MatrixP_
covariance of state estimate
Vectorm_
process disturbance
MatrixP_m_
covariance of disturbance estimate
Vectorcx_
C*x.
Vectory_
output
Vectorz_
measurement
Vectorx0_
initial state
MatrixP0_
covariance of initial state estimate
Vectorm0_
initial process disturbance
MatrixP0_m_
covariance of initial disturbance est.
MatrixA_
state matrix
MatrixB_
input matrix
Vectorg_
input gain
MatrixQ_
covariance of process noise
MatrixQ_m_
covariance of disturbance random walk
MatrixC_
output matrix
Vectord_
output bias
MatrixKe_
estimator gain
MatrixKe_m_
estimator gain for process disturbance
+
+
+

+ Public Function Details + # +

+

+ System + # +

+
System() =default
+

+

+ System + # +

+
System(
+    size_t n_u,
+    size_t n_x,
+    size_t n_y,
+    data_t dt,
+    data_t p0 =kDefaultP0,
+    data_t q0 =kDefaultQ0
+)
+

Parameters:

+
    +
  • n_u number of inputs
  • +
  • n_x number of states
  • +
  • n_y number of outputs
  • +
  • dt sample period
  • +
  • p0 diagonal elements for state estimate covariance
  • +
  • q0 diagonal elements for process noise covariance
  • +
+
+

+ ~System + # +

+
inline virtual ~System()
+

+

+ Filter + # +

+
void Filter(
+    const Vector & u_tm1,
+    const Vector & z
+)
+

Parameters:

+
    +
  • u_tm1 input at t-minus-1
  • +
  • z_t current measurement
  • +
+

Given current measurement and input, filter data to produce causal state estimates using Kalman filtering, which procedes by predicting the state and subsequently updating.

+
+

+ Simulate + # +

+
virtual const Vector & Simulate(
+    const Vector & u_tm1
+) =0
+

Parameters:

+
    +
  • u_tm1 input at time t-1
  • +
+

Return: simulated measurement at time t

+

Reimplemented by: lds::gaussian::System::Simulate, lds::poisson::System::Simulate

+
+

+ f + # +

+
inline void f(
+    const Vector & u,
+    bool do_add_noise =false
+)
+

Parameters:

+
    +
  • u input
  • +
  • do_add_noise whether to add simulated process noise
  • +
+
+

+ h + # +

+
virtual void h() =0
+

Reimplemented by: lds::gaussian::System::h, lds::poisson::System::h

+
+

+ h_ + # +

+
virtual Vector h_(
+    Vector x
+) =0
+

Parameters:

+
    +
  • x_t state at time t
  • +
+

Return: predicted state at time t + 1

+

Reimplemented by: lds::gaussian::System::h_, lds::poisson::System::h_

+
+

+ n_u + # +

+
inline size_t n_u() const
+

+

+ n_x + # +

+
inline size_t n_x() const
+

+

+ n_y + # +

+
inline size_t n_y() const
+

+

+ dt + # +

+
inline data_t dt() const
+

+

+ x + # +

+
inline const Vector & x() const
+

+

+ P + # +

+
inline const Matrix & P() const
+

+

+ m + # +

+
inline const Vector & m() const
+

+

+ P_m + # +

+
inline const Matrix & P_m() const
+

+

+ cx + # +

+
inline const Vector & cx() const
+

+

+ y + # +

+
inline const Vector & y() const
+

+

+ x0 + # +

+
inline const Vector & x0() const
+

+

+ m0 + # +

+
inline const Vector & m0() const
+

+

+ A + # +

+
inline const Matrix & A() const
+

+

+ B + # +

+
inline const Matrix & B() const
+

+

+ g + # +

+
inline const Vector & g() const
+

+

+ C + # +

+
inline const Matrix & C() const
+

+

+ d + # +

+
inline const Vector & d() const
+

+

+ Ke + # +

+
inline const Matrix & Ke() const
+

+

+ Ke_m + # +

+
inline const Matrix & Ke_m() const
+

+

+ Q + # +

+
inline const Matrix & Q()
+

+

+ Q_m + # +

+
inline const Matrix & Q_m()
+

+

+ P0 + # +

+
inline const Matrix & P0()
+

+

+ P0_m + # +

+
inline const Matrix & P0_m()
+

+

+ set_A + # +

+
inline void set_A(
+    const Matrix & A
+)
+

+

+ set_B + # +

+
inline void set_B(
+    const Matrix & B
+)
+

+

+ set_m + # +

+
inline void set_m(
+    const Vector & m,
+    bool do_force_assign =false
+)
+

+

+ set_g + # +

+
inline void set_g(
+    const Vector & g
+)
+

+

+ set_Q + # +

+
inline void set_Q(
+    const Matrix & Q
+)
+

+

+ set_Q_m + # +

+
inline void set_Q_m(
+    const Matrix & Q_m
+)
+

+

+ set_x0 + # +

+
inline void set_x0(
+    const Vector & x0
+)
+

+

+ set_P0 + # +

+
inline void set_P0(
+    const Matrix & P0
+)
+

+

+ set_P0_m + # +

+
inline void set_P0_m(
+    const Matrix & P0_m
+)
+

+

+ set_C + # +

+
inline void set_C(
+    const Matrix & C
+)
+

+

+ set_d + # +

+
inline void set_d(
+    const Vector & d
+)
+

+

+ set_x + # +

+
inline void set_x(
+    const Vector & x
+)
+

+

+ Reset + # +

+
void Reset()
+

+

+ nstep_pred_block + # +

+
std::vector< UniformMatrixList< kMatFreeDim2 > > nstep_pred_block(
+    UniformMatrixList< kMatFreeDim2 > u,
+    UniformMatrixList< kMatFreeDim2 > z,
+    size_t n_pred =1
+)
+

+

+ Print + # +

+
void Print()
+

+

+ Protected Function Details + # +

+

+ RecurseKe + # +

+
virtual void RecurseKe() =0
+

Reimplemented by: lds::gaussian::System::RecurseKe, lds::poisson::System::RecurseKe

+
+

+ InitVars + # +

+
void InitVars(
+    data_t p0 =kDefaultP0,
+    data_t q0 =kDefaultQ0
+)
+

+

+ Public Attribute Details + # +

+

+ do_adapt_m + # +

+
bool do_adapt_m {};
+

+

+ Protected Attribute Details + # +

+

+ n_x_ + # +

+
std::size_t n_x_ {};
+

+

+ n_u_ + # +

+
std::size_t n_u_ {};
+

+

+ n_y_ + # +

+
std::size_t n_y_ {};
+

+

+ dt_ + # +

+
data_t dt_ {};
+

+

+ x_ + # +

+
Vector x_;
+

+

+ P_ + # +

+
Matrix P_;
+

+

+ m_ + # +

+
Vector m_;
+

+

+ P_m_ + # +

+
Matrix P_m_;
+

+

+ cx_ + # +

+
Vector cx_;
+

+

+ y_ + # +

+
Vector y_;
+

+

+ z_ + # +

+
Vector z_;
+

+

+ x0_ + # +

+
Vector x0_;
+

+

+ P0_ + # +

+
Matrix P0_;
+

+

+ m0_ + # +

+
Vector m0_;
+

+

+ P0_m_ + # +

+
Matrix P0_m_;
+

+

+ A_ + # +

+
Matrix A_;
+

+

+ B_ + # +

+
Matrix B_;
+

+

+ g_ + # +

+
Vector g_;
+

+

+ Q_ + # +

+
Matrix Q_;
+

+

+ Q_m_ + # +

+
Matrix Q_m_;
+

+

+ C_ + # +

+
Matrix C_;
+

+

+ d_ + # +

+
Vector d_;
+

+

+ Ke_ + # +

+
Matrix Ke_;
+

+

+ Ke_m_ + # +

+
Matrix Ke_m_;
+

+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1_uniform_matrix_list/index.html b/docs/docs/api/classes/classlds_1_1_uniform_matrix_list/index.html new file mode 100644 index 00000000..62c607f1 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1_uniform_matrix_list/index.html @@ -0,0 +1,647 @@ + + + + + + + + + + + + + +lds::UniformMatrixList | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::UniformMatrixList + + +
+ + + + + + +
+ + + +

+ lds::UniformMatrixList + # +

+

More…

+

Inherits from std::vector< Matrix >

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformMatrixList() =default
Constructs a new UniformMatrixList.
UniformMatrixList(const std::vector< Matrix > & mats, std::array< size_t, 2 > dim ={0, 0})
Constructs a new UniformMatrixList by copying existing vector of Matrix if dimensions consistent.
UniformMatrixList(std::vector< Matrix > && mats, std::array< size_t, 2 > dim ={0, 0})
Constructs a new UniformMatrixList by moving existing vector of Matrix if dimensions consistent.
UniformMatrixList(std::initializer_list< Matrix > mats, std::array< size_t, 2 > dim ={0, 0})
Constructs a new UniformMatrixList from initializer_list of Matrix if dimensions consistent.
UniformMatrixList(const UniformMatrixList< D > & that)
Constructs a new UniformMatrixList (copy).
UniformMatrixList(UniformMatrixList< D > && that)
Constructs a new UniformMatrixList (move).
~UniformMatrixList() =default
Destroys the object.
const std::array< size_t, 2 > &dim(size_t n =0) const
gets dimensions of uniformly sized matrices
size_tsize()
size of container
const Matrix &at(size_t n)
gets reference to n^th element
voidSwap(Matrix & that, size_t n)
swaps input matrix with n^th matrix of list
UniformMatrixList< D > &operator=(const UniformMatrixList< D > & that)
assigns the contents (copy)
UniformMatrixList< D > &operator=(UniformMatrixList< D > && that)
assigns the contents (move)
voidappend(const Matrix & mat)
appends a matrix to the list
+

+ Detailed Description + # +

+
template <MatrixListFreeDim D =kMatFreeDimNone>
+class lds::UniformMatrixList;
+

+
+

+ Public Function Details + # +

+

+ UniformMatrixList + # +

+
UniformMatrixList() =default
+

+

+ UniformMatrixList + # +

+
explicit UniformMatrixList(
+    const std::vector< Matrix > & mats,
+    std::array< size_t, 2 > dim ={0, 0}
+)
+

Parameters:

+
    +
  • mats input matrices
  • +
  • dim dimensions
  • +
+
+

+ UniformMatrixList + # +

+
explicit UniformMatrixList(
+    std::vector< Matrix > && mats,
+    std::array< size_t, 2 > dim ={0, 0}
+)
+

Parameters:

+
    +
  • mats input matrices
  • +
  • dim dimensions
  • +
+
+

+ UniformMatrixList + # +

+
UniformMatrixList(
+    std::initializer_list< Matrix > mats,
+    std::array< size_t, 2 > dim ={0, 0}
+)
+

Parameters:

+
    +
  • mats input matrices
  • +
  • dim dimensions
  • +
+
+

+ UniformMatrixList + # +

+
UniformMatrixList(
+    const UniformMatrixList< D > & that
+)
+

Parameters:

+ +
+

+ UniformMatrixList + # +

+
UniformMatrixList(
+    UniformMatrixList< D > && that
+)
+

Parameters:

+ +
+

+ ~UniformMatrixList + # +

+
~UniformMatrixList() =default
+

+

+ dim + # +

+
inline const std::array< size_t, 2 > & dim(
+    size_t n =0
+) const
+

Parameters:

+
    +
  • n [optional] index in list of matrices
  • +
+

Return: dimensions

+
+

+ size + # +

+
inline size_t size()
+

+

+ at + # +

+
inline const Matrix & at(
+    size_t n
+)
+

+

+ Swap + # +

+
inline void Swap(
+    Matrix & that,
+    size_t n
+)
+

Parameters:

+
    +
  • that input matrix
  • +
  • n index where the matrix is moved
  • +
+
+

+ operator= + # +

+
inline UniformMatrixList< D > & operator=(
+    const UniformMatrixList< D > & that
+)
+

Parameters:

+ +

Return: reference to object

+
+

+ operator= + # +

+
inline UniformMatrixList< D > & operator=(
+    UniformMatrixList< D > && that
+)
+

Parameters:

+ +

Return: reference to object

+
+

+ append + # +

+
void append(
+    const Matrix & mat
+)
+

Parameters:

+
    +
  • mat input matrix
  • +
+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1_uniform_system_list/index.html b/docs/docs/api/classes/classlds_1_1_uniform_system_list/index.html new file mode 100644 index 00000000..f059bc29 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1_uniform_system_list/index.html @@ -0,0 +1,617 @@ + + + + + + + + + + + + + +lds::UniformSystemList | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::UniformSystemList + + +
+ + + + + + +
+ + + +

+ lds::UniformSystemList + # +

+

More…

+

Inherits from std::vector< System >

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformSystemList() =default
Constructs a new UniformSystemList.
UniformSystemList(const std::vector< System > & systems, std::array< size_t, 3 > dim ={0, 0, 0})
Constructs a new UniformSystemList by copying existing vector of System if dimensions consistent.
UniformSystemList(std::vector< System > && systems, std::array< size_t, 3 > dim ={0, 0, 0})
Constructs a new UniformSystemList by moving existing vector of System if dimensions consistent.
UniformSystemList(std::initializer_list< System > systems, std::array< size_t, 3 > dim ={0, 0, 0})
Constructs a new UniformSystemList from initializer_list of System if dimensions consistent.
UniformSystemList(const UniformSystemList & that)
Constructs a new UniformSystemList (copy).
UniformSystemList(UniformSystemList && that)
Constructs a new UniformSystemList (move).
~UniformSystemList() =default
Destroys the object.
const std::array< size_t, 3 > &dim() const
gets dimensions of the uniformly sized systems
size_tsize()
size of container
const System &at(size_t n)
gets reference to n^th element
voidSwap(System & that, size_t n)
swaps input system with n^th system of list
UniformSystemList &operator=(const UniformSystemList & that)
assigns the contents (copy)
UniformSystemList &operator=(UniformSystemList && that)
assigns the contents (move)
+

+ Detailed Description + # +

+
template <typename System >
+class lds::UniformSystemList;
+

+
+

+ Public Function Details + # +

+

+ UniformSystemList + # +

+
UniformSystemList() =default
+

+

+ UniformSystemList + # +

+
explicit UniformSystemList(
+    const std::vector< System > & systems,
+    std::array< size_t, 3 > dim ={0, 0, 0}
+)
+

Parameters:

+
    +
  • systems input systems
  • +
  • dim dimensions (n_u, n_x, n_y)
  • +
+
+

+ UniformSystemList + # +

+
explicit UniformSystemList(
+    std::vector< System > && systems,
+    std::array< size_t, 3 > dim ={0, 0, 0}
+)
+

Parameters:

+
    +
  • systems input systems
  • +
  • dim dimensions (n_u, n_x, n_y)
  • +
+
+

+ UniformSystemList + # +

+
UniformSystemList(
+    std::initializer_list< System > systems,
+    std::array< size_t, 3 > dim ={0, 0, 0}
+)
+

Parameters:

+
    +
  • systems input systems
  • +
  • dim dimensions (n_u, n_x, n_y)
  • +
+
+

+ UniformSystemList + # +

+
UniformSystemList(
+    const UniformSystemList & that
+)
+

Parameters:

+ +
+

+ UniformSystemList + # +

+
UniformSystemList(
+    UniformSystemList && that
+)
+

Parameters:

+ +
+

+ ~UniformSystemList + # +

+
~UniformSystemList() =default
+

+

+ dim + # +

+
inline const std::array< size_t, 3 > & dim() const
+

+

+ size + # +

+
inline size_t size()
+

+

+ at + # +

+
inline const System & at(
+    size_t n
+)
+

+

+ Swap + # +

+
inline void Swap(
+    System & that,
+    size_t n
+)
+

Parameters:

+
    +
  • that input system
  • +
  • n index where the system is moved
  • +
+
+

+ operator= + # +

+
inline UniformSystemList & operator=(
+    const UniformSystemList & that
+)
+

Parameters:

+ +

Return: reference to object

+
+

+ operator= + # +

+
inline UniformSystemList & operator=(
+    UniformSystemList && that
+)
+

Parameters:

+ +

Return: reference to object

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1_uniform_vector_list/index.html b/docs/docs/api/classes/classlds_1_1_uniform_vector_list/index.html new file mode 100644 index 00000000..36958dc5 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1_uniform_vector_list/index.html @@ -0,0 +1,600 @@ + + + + + + + + + + + + + +lds::UniformVectorList | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::UniformVectorList + + +
+ + + + + + +
+ + + +

+ lds::UniformVectorList + # +

+

Inherits from std::vector< Vector >

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformVectorList() =default
Constructs a new UniformVectorList.
UniformVectorList(const std::vector< Vector > & vecs, size_t dim =0)
Constructs a new UniformVectorList by copying existing vector of Vector if dimensions consistent.
UniformVectorList(std::vector< Vector > && vecs, size_t dim =0)
Constructs a new UniformVectorList by moving existing vector of Vector if dimensions consistent.
UniformVectorList(std::initializer_list< Vector > vecs, size_t dim =0)
Constructs a new UniformVectorList from initializer_list of Vector if dimensions consistent.
UniformVectorList(const UniformVectorList & that)
Constructs a new UniformVectorList (copy)
UniformVectorList(UniformVectorList && that)
Constructs a new UniformVectorList (move)
~UniformVectorList() =default
Destroys the object.
size_tdim() const
gets dimensions of the uniformly sized matrices
size_tsize()
size of container
const Vector &at(size_t n)
gets reference to n^th element
voidSwap(Vector & that, size_t n)
swaps input matrix with n^th vector of list
UniformVectorList &operator=(const UniformVectorList & that)
assigns the contents (copy)
UniformVectorList &operator=(UniformVectorList && that)
assigns the contents (move)
+
+
+

+ Public Function Details + # +

+

+ UniformVectorList + # +

+
UniformVectorList() =default
+

+

+ UniformVectorList + # +

+
explicit UniformVectorList(
+    const std::vector< Vector > & vecs,
+    size_t dim =0
+)
+

Parameters:

+
    +
  • vecs input vectors
  • +
  • dims dimension
  • +
+
+

+ UniformVectorList + # +

+
explicit UniformVectorList(
+    std::vector< Vector > && vecs,
+    size_t dim =0
+)
+

Parameters:

+
    +
  • vecs input vectors
  • +
  • dim dimension
  • +
+
+

+ UniformVectorList + # +

+
UniformVectorList(
+    std::initializer_list< Vector > vecs,
+    size_t dim =0
+)
+

Parameters:

+
    +
  • vecs input vectors
  • +
  • dim dimension
  • +
+
+

+ UniformVectorList + # +

+
UniformVectorList(
+    const UniformVectorList & that
+)
+

Parameters:

+ +
+

+ UniformVectorList + # +

+
UniformVectorList(
+    UniformVectorList && that
+)
+

Parameters:

+ +
+

+ ~UniformVectorList + # +

+
~UniformVectorList() =default
+

+

+ dim + # +

+
inline size_t dim() const
+

+

+ size + # +

+
inline size_t size()
+

+

+ at + # +

+
inline const Vector & at(
+    size_t n
+)
+

+

+ Swap + # +

+
inline void Swap(
+    Vector & that,
+    size_t n
+)
+

Parameters:

+
    +
  • that input vector
  • +
  • n index where the vector is moved
  • +
+
+

+ operator= + # +

+
inline UniformVectorList & operator=(
+    const UniformVectorList & that
+)
+

Parameters:

+ +

Return: reference to object

+
+

+ operator= + # +

+
inline UniformVectorList & operator=(
+    UniformVectorList && that
+)
+

Parameters:

+ +

Return: reference to object

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1gaussian_1_1_controller/index.html b/docs/docs/api/classes/classlds_1_1gaussian_1_1_controller/index.html new file mode 100644 index 00000000..93596e3f --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1gaussian_1_1_controller/index.html @@ -0,0 +1,560 @@ + + + + + + + + + + + + + +lds::gaussian::Controller | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::gaussian::Controller + + +
+ + + + + + +
+ + + +

+ lds::gaussian::Controller + # +

+

Gaussian-observation Controller Type. +
#include <lds_gaussian_ctrl.h>

+

Inherits from lds::Controller< System >

+

+ Public Functions + # +

+ + + + + + + + + + + + + +
Name
virtual voidset_y_ref(const Vector & y_ref) override
sets reference output
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Controller() =default
Constructs a new Controller.
Controller(const System & sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller.
Controller(System && sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller by moving the system object.
const Vector &Control(const Vector & z, bool do_control =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal (single-step)
const Vector &ControlOutputReference(const Vector & z, bool do_control =true, bool do_estimation =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal, given previously-set (single-step)
const System &sys() const
const Matrix &Kc() const
Get state feedback controller gain.
const Matrix &Kc_inty() const
Get integral controller gain.
const Matrix &Kc_u() const
Get input feedback controller gain.
const Vector &g_design() const
Get input gain used in controller design.
const Vector &u_ref() const
Get reference input.
const Vector &x_ref() const
Get reference state.
const Vector &y_ref() const
Get reference output.
size_tcontrol_type() const
Get controller type.
data_ttau_awu() const
Get time constant of anti-integral-windup.
data_tu_lb() const
Get control lower bound.
data_tu_ub() const
Get control upper bound.
voidset_sys(const System & sys)
Set system.
voidset_g_design(const Vector & g_design)
Set input gain used in controller design (g_design)
voidset_u_ref(const Vector & u_ref)
Set reference input (u_ref)
voidset_x_ref(const Vector & x_ref)
Set reference state (x_ref)
voidset_Kc(const Matrix & Kc)
Set state controller gain.
voidset_Kc_inty(const Matrix & Kc_inty)
Set integral controller gain.
voidset_Kc_u(const Matrix & Kc_u)
Set input controller gain.
voidset_tau_awu(data_t tau)
Set time constant of anti-integral-windup.
voidset_control_type(size_t control_type)
Sets the control type.
voidset_u_lb(data_t u_lb)
sets control lower bound
voidset_u_ub(data_t u_ub)
Sets control upper bound.
voidReset()
reset system and control variables.
voidPrint()
prints variables to stdout
+

Protected Attributes inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Systemsys_
underlying LDS
Vectoru_
control signal
Vectoru_return_
control signal that is returned to user
Vectorg_design_
input gain of the system used for controller design
Vectoru_ref_
reference input
Vectoru_ref_prev_
reference input at previous time step
Vectorx_ref_
reference state
Vectory_ref_
reference output
Vectorcx_ref_
MatrixKc_
state controller gain
MatrixKc_u_
input controller gain (optional when control updates \deltaU)
MatrixKc_inty_
integral controller gain
Vectordu_ref_
Vectordv_ref_
Vectorv_ref_
Vectordv_
Vectorv_
Control after g inversion (e.g., control in physical units)
Vectorint_e_
integrated error
Vectorint_e_awu_adjust_
anti-windup adjustment to intE
Vectoru_sat_
control signal after saturation (for antiWindup)
booldo_control_prev_
booldo_lock_control_prev_
boolu_saturated_
whether control signal has reached saturation limits
data_tu_lb_
lower bound on control
data_tu_ub_
upper bound on control
data_ttau_awu_
antiwindup time constant
data_tk_awu_
data_tt_since_control_onset_
time since control epoch onset
size_tcontrol_type_
controller type
+
+
+

+ Public Function Details + # +

+

+ set_y_ref + # +

+
inline virtual void set_y_ref(
+    const Vector & y_ref
+) override
+

Reimplements: lds::Controller::set_y_ref

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit/index.html b/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit/index.html new file mode 100644 index 00000000..7328fbb4 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit/index.html @@ -0,0 +1,553 @@ + + + + + + + + + + + + + +lds::gaussian::Fit | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::gaussian::Fit + + +
+ + + + + + +
+ + + +

+ lds::gaussian::Fit + # +

+

GLDS Fit Type. +
#include <lds_gaussian_fit.h>

+

Inherits from lds::Fit

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Fit() =default
Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt)
Constructs a new Fit.
virtual const Matrix &R() const override
gets measurement noise covariance
virtual voidset_R(const Matrix & R) override
sets measurement noise covariance
virtual Viewh(Matrix & y, const Matrix & x, size_t t) override
output function
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::Fit

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
virtual~Fit() =default
size_tn_u() const
gets number of inputs
size_tn_x() const
gets number of states
size_tn_y() const
gets number of outputs
data_tdt() const
gets sample period
const Matrix &A() const
gets state matrix
const Matrix &B() const
gets input matrix
const Vector &g() const
gets input gain
const Vector &m() const
gets process disturbance
const Matrix &Q() const
gets process noise covariance
const Vector &x0() const
gets initial state estimate
const Matrix &P0() const
gets covariance of initial state estimate
const Matrix &C() const
gets output matrix
const Vector &d() const
gets output bias
voidset_A(const Matrix & A)
sets state matrix
voidset_B(const Matrix & B)
sets input matrix
voidset_g(const Vector & g)
sets input gain/conversion factor
voidset_m(const Vector & m)
sets process disturbance
voidset_Q(const Matrix & Q)
sets process noise covariance
voidset_x0(const Vector & x0)
sets initial state estimate
voidset_P0(const Matrix & P0)
sets initial state estimate covariance
voidset_C(const Matrix & C)
sets output matrix
voidset_d(const Vector & d)
sets output bias
Viewf(Matrix & x, const Matrix & u, size_t t)
system dynamics function
Viewf(Matrix & x_pre, const Matrix & x_post, const Matrix & u, size_t t)
system dynamics function
+

Protected Attributes inherited from lds::Fit

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
data_tdt_
sample period
MatrixA_
state matrix
MatrixB_
input matrix
Vectorg_
input gain
Vectorm_
process noise mean
MatrixQ_
process noise cov
MatrixC_
output matrix
Vectord_
output bias
MatrixR_
measurement noise
Vectorx0_
initial state
MatrixP0_
initial covar
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
+
+
+

+ Public Function Details + # +

+

+ Fit + # +

+
Fit() =default
+

+

+ Fit + # +

+
Fit(
+    size_t n_u,
+    size_t n_x,
+    size_t n_y,
+    data_t dt
+)
+

Parameters:

+
    +
  • n_u number of inputs
  • +
  • n_x number of states
  • +
  • n_y number of outputs
  • +
  • dt sample period
  • +
+
+

+ R + # +

+
inline virtual const Matrix & R() const override
+

Reimplements: lds::Fit::R

+
+

+ set_R + # +

+
inline virtual void set_R(
+    const Matrix & R
+) override
+

Reimplements: lds::Fit::set_R

+
+

+ h + # +

+
inline virtual View h(
+    Matrix & y,
+    const Matrix & x,
+    size_t t
+) override
+

Parameters:

+
    +
  • y output estimate (over time)
  • +
  • x state estimate (over time)
  • +
  • t time index
  • +
+

Return: output

+

Reimplements: lds::Fit::h

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit_e_m/index.html b/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit_e_m/index.html new file mode 100644 index 00000000..b58ecd1e --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit_e_m/index.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + +lds::gaussian::FitEM | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::gaussian::FitEM + + +
+ + + + + + +
+ + + +

+ lds::gaussian::FitEM + # +

+

GLDS E-M Fit Type. More…

+


#include <lds_gaussian_fit_em.h>

+

Inherits from lds::EM< Fit >

+

+ Additional inherited members + # +

+

Public Functions inherited from lds::EM< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
EM() =default
Constructs a new EMFit type.
EM(size_t n_x, data_t dt, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train)
Constructs a new EMFit type.
EM(const Fit & fit0, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train)
Constructs a new EMFit type.
virtual~EM() =default
const Fit &Run(bool calc_dynamics =true, bool calc_Q =true, bool calc_init =true, bool calc_output =true, bool calc_measurement =true, size_t max_iter =100, data_t tol =1e-2)
Runs fitting by Expectation(E)-Maximization(M)
std::tuple< UniformMatrixList< kMatFreeDim2 >, UniformMatrixList< kMatFreeDim2 > >ReturnData()
Returns the input/output data to caller.
const std::vector< Matrix > &x() const
gets estimated state (over time)
const std::vector< Matrix > &y() const
gets estimated output (over time)
const Matrix &sum_E_x_t_x_t() const
gets state-input covariance
const Matrix &sum_E_xu_tm1_xu_tm1() const
gets state-input covariance (t-minus-1)
const Matrix &sum_E_xu_t_xu_tm1() const
gets single lag state-input covariance
size_tn_t_tot()
total number of time samples
const Vector &theta() const
gets parameters updated in M step
+

Protected Functions inherited from lds::EM< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
voidExpectation(bool force_common_initial =false)
Expectation step.
voidMaximization(bool calc_dynamics =true, bool calc_Q =true, bool calc_init =false, bool calc_output =false, bool calc_measurement =false)
Maximization step.
voidMaximizeDynamics()
voidMaximizeQ()
voidMaximizeInitial()
voidSmooth(bool force_common_initial)
get smoothed estimates
voidReset()
reset to initial conditions
voidInitVars()
Initializes the variables.
VectorUpdateTheta()
updates parameter list, theta
+

Protected Attributes inherited from lds::EM< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformMatrixList< kMatFreeDim2 >u_
input training data
UniformMatrixList< kMatFreeDim2 >z_
measurement training data
std::vector< Matrix >x_
state estimate
std::vector< Cube >P_
state estimate cov
std::vector< Cube >P_t_tm1_
single-lag state covariance
std::vector< Matrix >y_
output estimate
Matrixdiag_y_
Matrixsum_E_x_t_x_t_
state covariance (current time)
Matrixsum_E_xu_tm1_xu_tm1_
state-input covariance (t-minus-1)
Matrixsum_E_xu_t_xu_tm1_
single lag state-input covariance
Fitfit_
Vectortheta_
data_tdt_
sample period
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
size_tn_trials_
number of input/output data sequences
std::vector< size_t >n_t_
number of time steps
size_tn_t_tot_
total number of time steps across trials
+

+ Detailed Description + # +

+
class lds::gaussian::FitEM;
+
        This type is used in the process of fitting GLDS models by
+        expectation-maximization (EM).
+

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit_s_s_i_d/index.html b/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit_s_s_i_d/index.html new file mode 100644 index 00000000..56e74e1f --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1gaussian_1_1_fit_s_s_i_d/index.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + +lds::gaussian::FitSSID | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::gaussian::FitSSID + + +
+ + + + + + +
+ + + +

+ lds::gaussian::FitSSID + # +

+

Subspace Identification (SSID) for GLDS. +
#include <lds_gaussian_fit_ssid.h>

+

Inherits from lds::SSID< Fit >

+

+ Additional inherited members + # +

+

Public Functions inherited from lds::SSID< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Name
SSID() =default
Constructs a new SSIDFit type.
SSID(size_t n_x, size_t n_h, data_t dt, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train, const Vector & d =Vector(1).fill(-kInf))
Constructs a new SSIDFit type.
std::tuple< Fit, Vector >Run(SSIDWt ssid_wt)
Runs fitting by subspace identification (SSID)
std::tuple< UniformMatrixList< kMatFreeDim2 >, UniformMatrixList< kMatFreeDim2 > >ReturnData()
Returns the I/O data to caller.
+

Protected Functions inherited from lds::SSID< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
voidCalcD(data_t t_silence =0.1, data_t thresh_silence =0.001)
Using periods of silence in inputs (u), calculates the output \ bias (d)
voidCreateHankelDataMat()
Creates the block-hankel I/O data matrix.
voidCalcSVD(SSIDWt wt)
performs the singular value decomposition (SVD)
voidSolve(data_t wt_dc)
solves for LDS parameters
voidRecomputeExtObs()
recompute extended observability matrix from estimates of A, C
+

Protected Attributes inherited from lds::SSID< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformMatrixList< kMatFreeDim2 >u_
input training data
UniformMatrixList< kMatFreeDim2 >z_
measurement training data
MatrixD_
block-Hankel I/O data matrix
Fitfit_
fit
Matrixg_dc_
I/O gain @ DC.
data_tdt_
sample period
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
size_tn_h_
size_tn_trials_
number of input/output data sequences
std::vector< size_t >n_t_
number of time steps
size_tn_t_tot_
total number of time steps across trials
MatrixL_
lower triangle decomp of covariance matrix
Vectors_
singular values
Matrixext_obs_t_
extended observability matrix
+
+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1gaussian_1_1_switched_controller/index.html b/docs/docs/api/classes/classlds_1_1gaussian_1_1_switched_controller/index.html new file mode 100644 index 00000000..37c580ac --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1gaussian_1_1_switched_controller/index.html @@ -0,0 +1,658 @@ + + + + + + + + + + + + + +lds::gaussian::SwitchedController | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::gaussian::SwitchedController + + +
+ + + + + + +
+ + + +

+ lds::gaussian::SwitchedController + # +

+

Gaussian-observation SwitchedController Type. +
#include <lds_gaussian_sctrl.h>

+

Inherits from lds::SwitchedController< System >, lds::Controller< System >

+

+ Public Functions + # +

+ + + + + + + + + + + + + +
Name
virtual voidset_y_ref(const Vector & y_ref) override
sets reference output
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::SwitchedController< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
SwitchedController() =default
Constructs a new SwitchedController.
SwitchedController(const std::vector< System > & systems, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new SwitchedController.
SwitchedController(std::vector< System > && systems, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new SwitchedController (moves systems).
voidSwitch(size_t idx, bool do_force_switch =false)
Switch to a different sub-system/controller.
voidset_Kc(const UniformMatrixList<> & Kc)
sets state feedback gains
voidset_Kc(UniformMatrixList<> && Kc)
sets state feedback gains (moving)
voidset_Kc_inty(const UniformMatrixList<> & Kc_inty)
sets integral feedback gains
voidset_Kc_inty(UniformMatrixList<> && Kc_inty)
sets integral feedback gains (moving)
voidset_Kc_u(const UniformMatrixList<> & Kc_u)
sets input feedback gains
voidset_Kc_u(UniformMatrixList<> && Kc_u)
sets input feedback gains (moving)
voidset_g_design(const UniformVectorList & g)
sets input gain used during controller design
voidset_g_design(UniformVectorList && g)
sets input gain used during controller design (moving)
+

Protected Attributes inherited from lds::SwitchedController< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
std::vector< System >systems_
underlying sub-systems which are switched between
size_tn_sys_
number of systems
size_tidx_
current system/controller index.
UniformMatrixListKc_list_
UniformMatrixListKc_inty_list_
UniformMatrixListKc_u_list_
UniformVectorListg_design_list_
+

Public Functions inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Controller() =default
Constructs a new Controller.
Controller(const System & sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller.
Controller(System && sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller by moving the system object.
const Vector &Control(const Vector & z, bool do_control =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal (single-step)
const Vector &ControlOutputReference(const Vector & z, bool do_control =true, bool do_estimation =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal, given previously-set (single-step)
const System &sys() const
const Matrix &Kc() const
Get state feedback controller gain.
const Matrix &Kc_inty() const
Get integral controller gain.
const Matrix &Kc_u() const
Get input feedback controller gain.
const Vector &g_design() const
Get input gain used in controller design.
const Vector &u_ref() const
Get reference input.
const Vector &x_ref() const
Get reference state.
const Vector &y_ref() const
Get reference output.
size_tcontrol_type() const
Get controller type.
data_ttau_awu() const
Get time constant of anti-integral-windup.
data_tu_lb() const
Get control lower bound.
data_tu_ub() const
Get control upper bound.
voidset_sys(const System & sys)
Set system.
voidset_g_design(const Vector & g_design)
Set input gain used in controller design (g_design)
voidset_u_ref(const Vector & u_ref)
Set reference input (u_ref)
voidset_x_ref(const Vector & x_ref)
Set reference state (x_ref)
voidset_Kc(const Matrix & Kc)
Set state controller gain.
voidset_Kc_inty(const Matrix & Kc_inty)
Set integral controller gain.
voidset_Kc_u(const Matrix & Kc_u)
Set input controller gain.
voidset_tau_awu(data_t tau)
Set time constant of anti-integral-windup.
voidset_control_type(size_t control_type)
Sets the control type.
voidset_u_lb(data_t u_lb)
sets control lower bound
voidset_u_ub(data_t u_ub)
Sets control upper bound.
voidReset()
reset system and control variables.
voidPrint()
prints variables to stdout
+

Protected Attributes inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Systemsys_
underlying LDS
Vectoru_
control signal
Vectoru_return_
control signal that is returned to user
Vectorg_design_
input gain of the system used for controller design
Vectoru_ref_
reference input
Vectoru_ref_prev_
reference input at previous time step
Vectorx_ref_
reference state
Vectory_ref_
reference output
Vectorcx_ref_
MatrixKc_
state controller gain
MatrixKc_u_
input controller gain (optional when control updates \deltaU)
MatrixKc_inty_
integral controller gain
Vectordu_ref_
Vectordv_ref_
Vectorv_ref_
Vectordv_
Vectorv_
Control after g inversion (e.g., control in physical units)
Vectorint_e_
integrated error
Vectorint_e_awu_adjust_
anti-windup adjustment to intE
Vectoru_sat_
control signal after saturation (for antiWindup)
booldo_control_prev_
booldo_lock_control_prev_
boolu_saturated_
whether control signal has reached saturation limits
data_tu_lb_
lower bound on control
data_tu_ub_
upper bound on control
data_ttau_awu_
antiwindup time constant
data_tk_awu_
data_tt_since_control_onset_
time since control epoch onset
size_tcontrol_type_
controller type
+
+
+

+ Public Function Details + # +

+

+ set_y_ref + # +

+
inline virtual void set_y_ref(
+    const Vector & y_ref
+) override
+

Reimplements: lds::Controller::set_y_ref

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1gaussian_1_1_system/index.html b/docs/docs/api/classes/classlds_1_1gaussian_1_1_system/index.html new file mode 100644 index 00000000..427c8ed8 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1gaussian_1_1_system/index.html @@ -0,0 +1,855 @@ + + + + + + + + + + + + + +lds::gaussian::System | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::gaussian::System + + +
+ + + + + + +
+ + + +

+ lds::gaussian::System + # +

+

Gaussian LDS Type. +
#include <lds_gaussian_sys.h>

+

Inherits from lds::System

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
System() =default
Constructs a new System.
System(std::size_t n_u, std::size_t n_x, std::size_t n_y, data_t dt, data_t p0 =kDefaultP0, data_t q0 =kDefaultQ0, data_t r0 =kDefaultR0)
Constructs a new Gaussian System.
virtual const Vector &Simulate(const Vector & u_tm1) override
Simulate system measurement.
const Matrix &R() const
Get output noise covariance.
voidset_Q(const Matrix & Q)
voidset_R(const Matrix & R)
Set output noise covariance.
voidset_Ke(const Matrix & Ke)
Set estimator gain.
voidset_Ke_m(const Matrix & Ke_m)
Set disturbance estimator gain.
voidPrint()
Print system variables to stdout.
+

+ Protected Functions + # +

+ + + + + + + + + + + + + + + + + + + + + +
Name
virtual voidh() override
System output function.
virtual Vectorh_(Vector x) override
System output function: stateless.
virtual voidRecurseKe() override
Recursively update estimator gain.
+

+ Protected Attributes + # +

+ + + + + + + + + + + + + + + + + +
Name
MatrixR_
covariance of output noise
booldo_recurse_Ke_
whether to recursively calculate estimator gain
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::System

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
virtual~System()
voidFilter(const Vector & u_tm1, const Vector & z)
Filter data to produce causal state estimates.
voidf(const Vector & u, bool do_add_noise =false)
system dynamics function
size_tn_u() const
Get number of inputs.
size_tn_x() const
Get number of states.
size_tn_y() const
Get number of outputs.
data_tdt() const
Get sample period.
const Vector &x() const
Get current state.
const Matrix &P() const
Get covariance of state estimate.
const Vector &m() const
Get current process disturbance/bias.
const Matrix &P_m() const
Get covariance of process disturbance estimate.
const Vector &cx() const
Get C*x.
const Vector &y() const
Get output.
const Vector &x0() const
Get initial state.
const Vector &m0() const
Get initial disturbance.
const Matrix &A() const
Get state matrix.
const Matrix &B() const
Get input matrix.
const Vector &g() const
Get input gain/conversion factor.
const Matrix &C() const
Get output matrix.
const Vector &d() const
Get output bias.
const Matrix &Ke() const
Get estimator gain.
const Matrix &Ke_m() const
Get estimator gain for process disturbance (m)
const Matrix &Q()
Get process noise covariance.
const Matrix &Q_m()
Get process noise covariance of disturbance evoluation.
const Matrix &P0()
Get covariance of initial state.
const Matrix &P0_m()
Get covariance of initial process disturbance.
voidset_A(const Matrix & A)
Set state matrix.
voidset_B(const Matrix & B)
Set input matrix.
voidset_m(const Vector & m, bool do_force_assign =false)
Set process disturbance.
voidset_g(const Vector & g)
Set input gain.
voidset_Q_m(const Matrix & Q_m)
Set process noise covariance of disturbance evoluation.
voidset_x0(const Vector & x0)
Set initial state.
voidset_P0(const Matrix & P0)
Set covariance of initial state.
voidset_P0_m(const Matrix & P0_m)
Set covariance of initial process disturbance.
voidset_C(const Matrix & C)
Set output matrix.
voidset_d(const Vector & d)
Set output bias.
voidset_x(const Vector & x)
Set state of system.
voidReset()
Reset system variables.
std::vector< UniformMatrixList< kMatFreeDim2 > >nstep_pred_block(UniformMatrixList< kMatFreeDim2 > u, UniformMatrixList< kMatFreeDim2 > z, size_t n_pred =1)
+

Protected Functions inherited from lds::System

+ + + + + + + + + + + + + +
Name
voidInitVars(data_t p0 =kDefaultP0, data_t q0 =kDefaultQ0)
+

Public Attributes inherited from lds::System

+ + + + + + + + + + + + + +
Name
booldo_adapt_m
whether to adaptively estimate disturbance m
+

Protected Attributes inherited from lds::System

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
std::size_tn_x_
number of states
std::size_tn_u_
number of inputs
std::size_tn_y_
number of outputs
data_tdt_
sample period
Vectorx_
state
MatrixP_
covariance of state estimate
Vectorm_
process disturbance
MatrixP_m_
covariance of disturbance estimate
Vectorcx_
C*x.
Vectory_
output
Vectorz_
measurement
Vectorx0_
initial state
MatrixP0_
covariance of initial state estimate
Vectorm0_
initial process disturbance
MatrixP0_m_
covariance of initial disturbance est.
MatrixA_
state matrix
MatrixB_
input matrix
Vectorg_
input gain
MatrixQ_
covariance of process noise
MatrixQ_m_
covariance of disturbance random walk
MatrixC_
output matrix
Vectord_
output bias
MatrixKe_
estimator gain
MatrixKe_m_
estimator gain for process disturbance
+
+
+

+ Public Function Details + # +

+

+ System + # +

+
System() =default
+

+

+ System + # +

+
System(
+    std::size_t n_u,
+    std::size_t n_x,
+    std::size_t n_y,
+    data_t dt,
+    data_t p0 =kDefaultP0,
+    data_t q0 =kDefaultQ0,
+    data_t r0 =kDefaultR0
+)
+

Parameters:

+
    +
  • n_u number of inputs (u)
  • +
  • n_x number of states (x)
  • +
  • n_y number of outputs (y)
  • +
  • dt sample period
  • +
  • p0 [optional] initial diagonal elements of state estimate covariance (P)
  • +
  • q0 [optional] initial diagonal elements of process noise covariance (Q)
  • +
  • r0 [optional] initial diagonal elements of output noise covariance (R)
  • +
+
+

+ Simulate + # +

+
virtual const Vector & Simulate(
+    const Vector & u_tm1
+) override
+

Parameters:

+
    +
  • u_tm1 input at t-1
  • +
+

Return: z measurement

+

Reimplements: lds::System::Simulate

+

Simulate system and produce measurement

+
+

+ R + # +

+
inline const Matrix & R() const
+

+

+ set_Q + # +

+
inline void set_Q(
+    const Matrix & Q
+)
+

+

+ set_R + # +

+
inline void set_R(
+    const Matrix & R
+)
+

+

+ set_Ke + # +

+
inline void set_Ke(
+    const Matrix & Ke
+)
+

+

+ set_Ke_m + # +

+
inline void set_Ke_m(
+    const Matrix & Ke_m
+)
+

+

+ Print + # +

+
void Print()
+

+

+ Protected Function Details + # +

+

+ h + # +

+
inline virtual void h() override
+

Reimplements: lds::System::h

+
+

+ h_ + # +

+
inline virtual Vector h_(
+    Vector x
+) override
+

Reimplements: lds::System::h_

+
+

+ RecurseKe + # +

+
virtual void RecurseKe() override
+

Reimplements: lds::System::RecurseKe

+
+

+ Protected Attribute Details + # +

+

+ R_ + # +

+
Matrix R_;
+

+

+ do_recurse_Ke_ + # +

+
bool do_recurse_Ke_ {};
+

+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1poisson_1_1_controller/index.html b/docs/docs/api/classes/classlds_1_1poisson_1_1_controller/index.html new file mode 100644 index 00000000..0b49e7ac --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1poisson_1_1_controller/index.html @@ -0,0 +1,560 @@ + + + + + + + + + + + + + +lds::poisson::Controller | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::poisson::Controller + + +
+ + + + + + +
+ + + +

+ lds::poisson::Controller + # +

+

PLDS Controller Type. +
#include <lds_poisson_ctrl.h>

+

Inherits from lds::Controller< System >

+

+ Public Functions + # +

+ + + + + + + + + + + + + +
Name
virtual voidset_y_ref(const Vector & y_ref) override
Set reference output.
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Controller() =default
Constructs a new Controller.
Controller(const System & sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller.
Controller(System && sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller by moving the system object.
const Vector &Control(const Vector & z, bool do_control =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal (single-step)
const Vector &ControlOutputReference(const Vector & z, bool do_control =true, bool do_estimation =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal, given previously-set (single-step)
const System &sys() const
const Matrix &Kc() const
Get state feedback controller gain.
const Matrix &Kc_inty() const
Get integral controller gain.
const Matrix &Kc_u() const
Get input feedback controller gain.
const Vector &g_design() const
Get input gain used in controller design.
const Vector &u_ref() const
Get reference input.
const Vector &x_ref() const
Get reference state.
const Vector &y_ref() const
Get reference output.
size_tcontrol_type() const
Get controller type.
data_ttau_awu() const
Get time constant of anti-integral-windup.
data_tu_lb() const
Get control lower bound.
data_tu_ub() const
Get control upper bound.
voidset_sys(const System & sys)
Set system.
voidset_g_design(const Vector & g_design)
Set input gain used in controller design (g_design)
voidset_u_ref(const Vector & u_ref)
Set reference input (u_ref)
voidset_x_ref(const Vector & x_ref)
Set reference state (x_ref)
voidset_Kc(const Matrix & Kc)
Set state controller gain.
voidset_Kc_inty(const Matrix & Kc_inty)
Set integral controller gain.
voidset_Kc_u(const Matrix & Kc_u)
Set input controller gain.
voidset_tau_awu(data_t tau)
Set time constant of anti-integral-windup.
voidset_control_type(size_t control_type)
Sets the control type.
voidset_u_lb(data_t u_lb)
sets control lower bound
voidset_u_ub(data_t u_ub)
Sets control upper bound.
voidReset()
reset system and control variables.
voidPrint()
prints variables to stdout
+

Protected Attributes inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Systemsys_
underlying LDS
Vectoru_
control signal
Vectoru_return_
control signal that is returned to user
Vectorg_design_
input gain of the system used for controller design
Vectoru_ref_
reference input
Vectoru_ref_prev_
reference input at previous time step
Vectorx_ref_
reference state
Vectory_ref_
reference output
Vectorcx_ref_
MatrixKc_
state controller gain
MatrixKc_u_
input controller gain (optional when control updates \deltaU)
MatrixKc_inty_
integral controller gain
Vectordu_ref_
Vectordv_ref_
Vectorv_ref_
Vectordv_
Vectorv_
Control after g inversion (e.g., control in physical units)
Vectorint_e_
integrated error
Vectorint_e_awu_adjust_
anti-windup adjustment to intE
Vectoru_sat_
control signal after saturation (for antiWindup)
booldo_control_prev_
booldo_lock_control_prev_
boolu_saturated_
whether control signal has reached saturation limits
data_tu_lb_
lower bound on control
data_tu_ub_
upper bound on control
data_ttau_awu_
antiwindup time constant
data_tk_awu_
data_tt_since_control_onset_
time since control epoch onset
size_tcontrol_type_
controller type
+
+
+

+ Public Function Details + # +

+

+ set_y_ref + # +

+
inline virtual void set_y_ref(
+    const Vector & y_ref
+) override
+

Reimplements: lds::Controller::set_y_ref

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1poisson_1_1_fit/index.html b/docs/docs/api/classes/classlds_1_1poisson_1_1_fit/index.html new file mode 100644 index 00000000..bafb01b3 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1poisson_1_1_fit/index.html @@ -0,0 +1,553 @@ + + + + + + + + + + + + + +lds::poisson::Fit | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::poisson::Fit + + +
+ + + + + + +
+ + + +

+ lds::poisson::Fit + # +

+

PLDS Fit Type. +
#include <lds_poisson_fit.h>

+

Inherits from lds::Fit

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Fit() =default
Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt)
Constructs a new Fit.
virtual Viewh(Matrix & y, const Matrix & x, size_t t) override
output function
virtual voidset_R(const Matrix & R) override
sets output noise covariance (if any)
virtual const Matrix &R() const override
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::Fit

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
virtual~Fit() =default
size_tn_u() const
gets number of inputs
size_tn_x() const
gets number of states
size_tn_y() const
gets number of outputs
data_tdt() const
gets sample period
const Matrix &A() const
gets state matrix
const Matrix &B() const
gets input matrix
const Vector &g() const
gets input gain
const Vector &m() const
gets process disturbance
const Matrix &Q() const
gets process noise covariance
const Vector &x0() const
gets initial state estimate
const Matrix &P0() const
gets covariance of initial state estimate
const Matrix &C() const
gets output matrix
const Vector &d() const
gets output bias
voidset_A(const Matrix & A)
sets state matrix
voidset_B(const Matrix & B)
sets input matrix
voidset_g(const Vector & g)
sets input gain/conversion factor
voidset_m(const Vector & m)
sets process disturbance
voidset_Q(const Matrix & Q)
sets process noise covariance
voidset_x0(const Vector & x0)
sets initial state estimate
voidset_P0(const Matrix & P0)
sets initial state estimate covariance
voidset_C(const Matrix & C)
sets output matrix
voidset_d(const Vector & d)
sets output bias
Viewf(Matrix & x, const Matrix & u, size_t t)
system dynamics function
Viewf(Matrix & x_pre, const Matrix & x_post, const Matrix & u, size_t t)
system dynamics function
+

Protected Attributes inherited from lds::Fit

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
data_tdt_
sample period
MatrixA_
state matrix
MatrixB_
input matrix
Vectorg_
input gain
Vectorm_
process noise mean
MatrixQ_
process noise cov
MatrixC_
output matrix
Vectord_
output bias
MatrixR_
measurement noise
Vectorx0_
initial state
MatrixP0_
initial covar
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
+
+
+

+ Public Function Details + # +

+

+ Fit + # +

+
Fit() =default
+

+

+ Fit + # +

+
inline Fit(
+    size_t n_u,
+    size_t n_x,
+    size_t n_y,
+    data_t dt
+)
+

Parameters:

+
    +
  • n_u number of inputs
  • +
  • n_x number of states
  • +
  • n_y number of outputs
  • +
  • dt sample period
  • +
+
+

+ h + # +

+
inline virtual View h(
+    Matrix & y,
+    const Matrix & x,
+    size_t t
+) override
+

Parameters:

+
    +
  • y output estimate (over time)
  • +
  • x state estimate (over time)
  • +
  • t time index
  • +
+

Return: output

+

Reimplements: lds::Fit::h

+
+

+ set_R + # +

+
inline virtual void set_R(
+    const Matrix & R
+) override
+

Reimplements: lds::Fit::set_R

+
+

+ R + # +

+
inline virtual const Matrix & R() const override
+

Reimplements: lds::Fit::R

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1poisson_1_1_fit_e_m/index.html b/docs/docs/api/classes/classlds_1_1poisson_1_1_fit_e_m/index.html new file mode 100644 index 00000000..7033af4b --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1poisson_1_1_fit_e_m/index.html @@ -0,0 +1,465 @@ + + + + + + + + + + + + + +lds::poisson::FitEM | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::poisson::FitEM + + +
+ + + + + + +
+ + + +

+ lds::poisson::FitEM + # +

+

PLDS E-M Fit Type. More…

+


#include <lds_poisson_fit_em.h>

+

Inherits from lds::EM< Fit >

+

+ Additional inherited members + # +

+

Public Functions inherited from lds::EM< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
EM() =default
Constructs a new EMFit type.
EM(size_t n_x, data_t dt, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train)
Constructs a new EMFit type.
EM(const Fit & fit0, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train)
Constructs a new EMFit type.
virtual~EM() =default
const Fit &Run(bool calc_dynamics =true, bool calc_Q =true, bool calc_init =true, bool calc_output =true, bool calc_measurement =true, size_t max_iter =100, data_t tol =1e-2)
Runs fitting by Expectation(E)-Maximization(M)
std::tuple< UniformMatrixList< kMatFreeDim2 >, UniformMatrixList< kMatFreeDim2 > >ReturnData()
Returns the input/output data to caller.
const std::vector< Matrix > &x() const
gets estimated state (over time)
const std::vector< Matrix > &y() const
gets estimated output (over time)
const Matrix &sum_E_x_t_x_t() const
gets state-input covariance
const Matrix &sum_E_xu_tm1_xu_tm1() const
gets state-input covariance (t-minus-1)
const Matrix &sum_E_xu_t_xu_tm1() const
gets single lag state-input covariance
size_tn_t_tot()
total number of time samples
const Vector &theta() const
gets parameters updated in M step
+

Protected Functions inherited from lds::EM< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
voidExpectation(bool force_common_initial =false)
Expectation step.
voidMaximization(bool calc_dynamics =true, bool calc_Q =true, bool calc_init =false, bool calc_output =false, bool calc_measurement =false)
Maximization step.
voidMaximizeDynamics()
voidMaximizeQ()
voidMaximizeInitial()
voidSmooth(bool force_common_initial)
get smoothed estimates
voidReset()
reset to initial conditions
voidInitVars()
Initializes the variables.
VectorUpdateTheta()
updates parameter list, theta
+

Protected Attributes inherited from lds::EM< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformMatrixList< kMatFreeDim2 >u_
input training data
UniformMatrixList< kMatFreeDim2 >z_
measurement training data
std::vector< Matrix >x_
state estimate
std::vector< Cube >P_
state estimate cov
std::vector< Cube >P_t_tm1_
single-lag state covariance
std::vector< Matrix >y_
output estimate
Matrixdiag_y_
Matrixsum_E_x_t_x_t_
state covariance (current time)
Matrixsum_E_xu_tm1_xu_tm1_
state-input covariance (t-minus-1)
Matrixsum_E_xu_t_xu_tm1_
single lag state-input covariance
Fitfit_
Vectortheta_
data_tdt_
sample period
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
size_tn_trials_
number of input/output data sequences
std::vector< size_t >n_t_
number of time steps
size_tn_t_tot_
total number of time steps across trials
+

+ Detailed Description + # +

+
class lds::poisson::FitEM;
+
        This type is used in the process of fitting PLDS models by
+        expectation-maximization (EM).
+

+
+
+

Updated on 3 April 2025 at 13:48:29 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1poisson_1_1_fit_s_s_i_d/index.html b/docs/docs/api/classes/classlds_1_1poisson_1_1_fit_s_s_i_d/index.html new file mode 100644 index 00000000..db283d70 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1poisson_1_1_fit_s_s_i_d/index.html @@ -0,0 +1,392 @@ + + + + + + + + + + + + + +lds::poisson::FitSSID | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::poisson::FitSSID + + +
+ + + + + + +
+ + + +

+ lds::poisson::FitSSID + # +

+

Subspace Identification (SSID) for PLDS. +
#include <lds_poisson_fit_ssid.h>

+

Inherits from lds::SSID< Fit >

+

+ Additional inherited members + # +

+

Public Functions inherited from lds::SSID< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Name
SSID() =default
Constructs a new SSIDFit type.
SSID(size_t n_x, size_t n_h, data_t dt, UniformMatrixList< kMatFreeDim2 > && u_train, UniformMatrixList< kMatFreeDim2 > && z_train, const Vector & d =Vector(1).fill(-kInf))
Constructs a new SSIDFit type.
std::tuple< Fit, Vector >Run(SSIDWt ssid_wt)
Runs fitting by subspace identification (SSID)
std::tuple< UniformMatrixList< kMatFreeDim2 >, UniformMatrixList< kMatFreeDim2 > >ReturnData()
Returns the I/O data to caller.
+

Protected Functions inherited from lds::SSID< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
voidCalcD(data_t t_silence =0.1, data_t thresh_silence =0.001)
Using periods of silence in inputs (u), calculates the output \ bias (d)
voidCreateHankelDataMat()
Creates the block-hankel I/O data matrix.
voidCalcSVD(SSIDWt wt)
performs the singular value decomposition (SVD)
voidSolve(data_t wt_dc)
solves for LDS parameters
voidRecomputeExtObs()
recompute extended observability matrix from estimates of A, C
+

Protected Attributes inherited from lds::SSID< Fit >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
UniformMatrixList< kMatFreeDim2 >u_
input training data
UniformMatrixList< kMatFreeDim2 >z_
measurement training data
MatrixD_
block-Hankel I/O data matrix
Fitfit_
fit
Matrixg_dc_
I/O gain @ DC.
data_tdt_
sample period
size_tn_u_
number of inputs
size_tn_x_
number of states
size_tn_y_
number of outputs
size_tn_h_
size_tn_trials_
number of input/output data sequences
std::vector< size_t >n_t_
number of time steps
size_tn_t_tot_
total number of time steps across trials
MatrixL_
lower triangle decomp of covariance matrix
Vectors_
singular values
Matrixext_obs_t_
extended observability matrix
+
+
+
+

Updated on 3 April 2025 at 13:48:30 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1poisson_1_1_switched_controller/index.html b/docs/docs/api/classes/classlds_1_1poisson_1_1_switched_controller/index.html new file mode 100644 index 00000000..ef07686d --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1poisson_1_1_switched_controller/index.html @@ -0,0 +1,658 @@ + + + + + + + + + + + + + +lds::poisson::SwitchedController | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::poisson::SwitchedController + + +
+ + + + + + +
+ + + +

+ lds::poisson::SwitchedController + # +

+

Poisson-observation SwitchedController Type. +
#include <lds_poisson_sctrl.h>

+

Inherits from lds::SwitchedController< System >, lds::Controller< System >

+

+ Public Functions + # +

+ + + + + + + + + + + + + +
Name
virtual voidset_y_ref(const Vector & y_ref) override
Set reference output.
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::SwitchedController< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
SwitchedController() =default
Constructs a new SwitchedController.
SwitchedController(const std::vector< System > & systems, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new SwitchedController.
SwitchedController(std::vector< System > && systems, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new SwitchedController (moves systems).
voidSwitch(size_t idx, bool do_force_switch =false)
Switch to a different sub-system/controller.
voidset_Kc(const UniformMatrixList<> & Kc)
sets state feedback gains
voidset_Kc(UniformMatrixList<> && Kc)
sets state feedback gains (moving)
voidset_Kc_inty(const UniformMatrixList<> & Kc_inty)
sets integral feedback gains
voidset_Kc_inty(UniformMatrixList<> && Kc_inty)
sets integral feedback gains (moving)
voidset_Kc_u(const UniformMatrixList<> & Kc_u)
sets input feedback gains
voidset_Kc_u(UniformMatrixList<> && Kc_u)
sets input feedback gains (moving)
voidset_g_design(const UniformVectorList & g)
sets input gain used during controller design
voidset_g_design(UniformVectorList && g)
sets input gain used during controller design (moving)
+

Protected Attributes inherited from lds::SwitchedController< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
std::vector< System >systems_
underlying sub-systems which are switched between
size_tn_sys_
number of systems
size_tidx_
current system/controller index.
UniformMatrixListKc_list_
UniformMatrixListKc_inty_list_
UniformMatrixListKc_u_list_
UniformVectorListg_design_list_
+

Public Functions inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Controller() =default
Constructs a new Controller.
Controller(const System & sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller.
Controller(System && sys, data_t u_lb, data_t u_ub, size_t control_type =0)
Constructs a new Controller by moving the system object.
const Vector &Control(const Vector & z, bool do_control =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal (single-step)
const Vector &ControlOutputReference(const Vector & z, bool do_control =true, bool do_estimation =true, bool do_lock_control =false, data_t sigma_soft_start =0, data_t sigma_u_noise =0, bool do_reset_at_control_onset =true)
updates control signal, given previously-set (single-step)
const System &sys() const
const Matrix &Kc() const
Get state feedback controller gain.
const Matrix &Kc_inty() const
Get integral controller gain.
const Matrix &Kc_u() const
Get input feedback controller gain.
const Vector &g_design() const
Get input gain used in controller design.
const Vector &u_ref() const
Get reference input.
const Vector &x_ref() const
Get reference state.
const Vector &y_ref() const
Get reference output.
size_tcontrol_type() const
Get controller type.
data_ttau_awu() const
Get time constant of anti-integral-windup.
data_tu_lb() const
Get control lower bound.
data_tu_ub() const
Get control upper bound.
voidset_sys(const System & sys)
Set system.
voidset_g_design(const Vector & g_design)
Set input gain used in controller design (g_design)
voidset_u_ref(const Vector & u_ref)
Set reference input (u_ref)
voidset_x_ref(const Vector & x_ref)
Set reference state (x_ref)
voidset_Kc(const Matrix & Kc)
Set state controller gain.
voidset_Kc_inty(const Matrix & Kc_inty)
Set integral controller gain.
voidset_Kc_u(const Matrix & Kc_u)
Set input controller gain.
voidset_tau_awu(data_t tau)
Set time constant of anti-integral-windup.
voidset_control_type(size_t control_type)
Sets the control type.
voidset_u_lb(data_t u_lb)
sets control lower bound
voidset_u_ub(data_t u_ub)
Sets control upper bound.
voidReset()
reset system and control variables.
voidPrint()
prints variables to stdout
+

Protected Attributes inherited from lds::Controller< System >

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Systemsys_
underlying LDS
Vectoru_
control signal
Vectoru_return_
control signal that is returned to user
Vectorg_design_
input gain of the system used for controller design
Vectoru_ref_
reference input
Vectoru_ref_prev_
reference input at previous time step
Vectorx_ref_
reference state
Vectory_ref_
reference output
Vectorcx_ref_
MatrixKc_
state controller gain
MatrixKc_u_
input controller gain (optional when control updates \deltaU)
MatrixKc_inty_
integral controller gain
Vectordu_ref_
Vectordv_ref_
Vectorv_ref_
Vectordv_
Vectorv_
Control after g inversion (e.g., control in physical units)
Vectorint_e_
integrated error
Vectorint_e_awu_adjust_
anti-windup adjustment to intE
Vectoru_sat_
control signal after saturation (for antiWindup)
booldo_control_prev_
booldo_lock_control_prev_
boolu_saturated_
whether control signal has reached saturation limits
data_tu_lb_
lower bound on control
data_tu_ub_
upper bound on control
data_ttau_awu_
antiwindup time constant
data_tk_awu_
data_tt_since_control_onset_
time since control epoch onset
size_tcontrol_type_
controller type
+
+
+

+ Public Function Details + # +

+

+ set_y_ref + # +

+
inline virtual void set_y_ref(
+    const Vector & y_ref
+) override
+

Reimplements: lds::Controller::set_y_ref

+
+
+

Updated on 3 April 2025 at 13:48:30 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/classlds_1_1poisson_1_1_system/index.html b/docs/docs/api/classes/classlds_1_1poisson_1_1_system/index.html new file mode 100644 index 00000000..57ec4df0 --- /dev/null +++ b/docs/docs/api/classes/classlds_1_1poisson_1_1_system/index.html @@ -0,0 +1,733 @@ + + + + + + + + + + + + + +lds::poisson::System | LDS C&E + + + + + + + + + + + +
+ + +
+
+ +
+ + + lds::poisson::System + + +
+ + + + + + +
+ + + +

+ lds::poisson::System + # +

+

Poisson System type. +
#include <lds_poisson_sys.h>

+

Inherits from lds::System

+

+ Public Functions + # +

+ + + + + + + + + + + + + + + + + + + + + +
Name
System() =default
Constructs a new System.
System(std::size_t n_u, std::size_t n_x, std::size_t n_y, data_t dt, data_t p0 =kDefaultP0, data_t q0 =kDefaultQ0)
Constructs a new Poisson System.
virtual const Vector &Simulate(const Vector & u_tm1) override
Simulate system measurement.
+

+ Protected Functions + # +

+ + + + + + + + + + + + + + + + + + + + + +
Name
virtual voidh() override
System output function.
virtual Vectorh_(Vector x) override
System output function: stateless.
virtual voidRecurseKe() override
Recursively recalculate estimator gain (Ke)
+

+ Additional inherited members + # +

+

Public Functions inherited from lds::System

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
virtual~System()
voidFilter(const Vector & u_tm1, const Vector & z)
Filter data to produce causal state estimates.
voidf(const Vector & u, bool do_add_noise =false)
system dynamics function
size_tn_u() const
Get number of inputs.
size_tn_x() const
Get number of states.
size_tn_y() const
Get number of outputs.
data_tdt() const
Get sample period.
const Vector &x() const
Get current state.
const Matrix &P() const
Get covariance of state estimate.
const Vector &m() const
Get current process disturbance/bias.
const Matrix &P_m() const
Get covariance of process disturbance estimate.
const Vector &cx() const
Get C*x.
const Vector &y() const
Get output.
const Vector &x0() const
Get initial state.
const Vector &m0() const
Get initial disturbance.
const Matrix &A() const
Get state matrix.
const Matrix &B() const
Get input matrix.
const Vector &g() const
Get input gain/conversion factor.
const Matrix &C() const
Get output matrix.
const Vector &d() const
Get output bias.
const Matrix &Ke() const
Get estimator gain.
const Matrix &Ke_m() const
Get estimator gain for process disturbance (m)
const Matrix &Q()
Get process noise covariance.
const Matrix &Q_m()
Get process noise covariance of disturbance evoluation.
const Matrix &P0()
Get covariance of initial state.
const Matrix &P0_m()
Get covariance of initial process disturbance.
voidset_A(const Matrix & A)
Set state matrix.
voidset_B(const Matrix & B)
Set input matrix.
voidset_m(const Vector & m, bool do_force_assign =false)
Set process disturbance.
voidset_g(const Vector & g)
Set input gain.
voidset_Q(const Matrix & Q)
Set process noise covariance.
voidset_Q_m(const Matrix & Q_m)
Set process noise covariance of disturbance evoluation.
voidset_x0(const Vector & x0)
Set initial state.
voidset_P0(const Matrix & P0)
Set covariance of initial state.
voidset_P0_m(const Matrix & P0_m)
Set covariance of initial process disturbance.
voidset_C(const Matrix & C)
Set output matrix.
voidset_d(const Vector & d)
Set output bias.
voidset_x(const Vector & x)
Set state of system.
voidReset()
Reset system variables.
std::vector< UniformMatrixList< kMatFreeDim2 > >nstep_pred_block(UniformMatrixList< kMatFreeDim2 > u, UniformMatrixList< kMatFreeDim2 > z, size_t n_pred =1)
voidPrint()
Print system variables to stdout.
+

Protected Functions inherited from lds::System

+ + + + + + + + + + + + + +
Name
voidInitVars(data_t p0 =kDefaultP0, data_t q0 =kDefaultQ0)
+

Public Attributes inherited from lds::System

+ + + + + + + + + + + + + +
Name
booldo_adapt_m
whether to adaptively estimate disturbance m
+

Protected Attributes inherited from lds::System

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
std::size_tn_x_
number of states
std::size_tn_u_
number of inputs
std::size_tn_y_
number of outputs
data_tdt_
sample period
Vectorx_
state
MatrixP_
covariance of state estimate
Vectorm_
process disturbance
MatrixP_m_
covariance of disturbance estimate
Vectorcx_
C*x.
Vectory_
output
Vectorz_
measurement
Vectorx0_
initial state
MatrixP0_
covariance of initial state estimate
Vectorm0_
initial process disturbance
MatrixP0_m_
covariance of initial disturbance est.
MatrixA_
state matrix
MatrixB_
input matrix
Vectorg_
input gain
MatrixQ_
covariance of process noise
MatrixQ_m_
covariance of disturbance random walk
MatrixC_
output matrix
Vectord_
output bias
MatrixKe_
estimator gain
MatrixKe_m_
estimator gain for process disturbance
+
+
+

+ Public Function Details + # +

+

+ System + # +

+
System() =default
+

+

+ System + # +

+
System(
+    std::size_t n_u,
+    std::size_t n_x,
+    std::size_t n_y,
+    data_t dt,
+    data_t p0 =kDefaultP0,
+    data_t q0 =kDefaultQ0
+)
+

Parameters:

+
    +
  • n_u number of inputs
  • +
  • n_x number of states
  • +
  • n_y number of outputs
  • +
  • dt sample period
  • +
  • p0 [optional] initial diagonal elements of state estimate covariance (P)
  • +
  • q0 [optional] initial diagonal elements of process noise covariance (Q)
  • +
+
+

+ Simulate + # +

+
virtual const Vector & Simulate(
+    const Vector & u_tm1
+) override
+

Parameters:

+
    +
  • u_tm1 input at t-1
  • +
+

Return: z measurement

+

Reimplements: lds::System::Simulate

+

Simulate system and produce measurement

+
+

+ Protected Function Details + # +

+

+ h + # +

+
inline virtual void h() override
+

Reimplements: lds::System::h

+
+

+ h_ + # +

+
inline virtual Vector h_(
+    Vector x
+) override
+

Reimplements: lds::System::h_

+
+

+ RecurseKe + # +

+
virtual void RecurseKe() override
+

Reimplements: lds::System::RecurseKe

+

Recursively recalculate estimator gain (Ke).

+

References:

+

Smith AC, Brown EN. (2003) Estimating a State-Space Model from Point Process Observations. Neural Computation 15.

+

Eden UT, …, Brown EN. (2004) Dynamic Analysis of Neural Encoding by Point Process Adaptive Filtering Neural Computation 16.

+
+
+

Updated on 3 April 2025 at 13:48:30 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/classes/index.html b/docs/docs/api/classes/index.html index 5e959142..d9d852d6 100644 --- a/docs/docs/api/classes/index.html +++ b/docs/docs/api/classes/index.html @@ -3,31 +3,110 @@ - - - - - + + + + + + + Classes | LDS C&E - + + + + + + +
+ + +
+
+ +
+ + + API Reference + + +
+ + + + + + +
+ + + +

+ API Reference + # +

+

The API documentation is organized into the following sections:

+
    +
  • Classes - Documentation for all classes
  • +
  • Namespaces - Documentation for all namespaces
  • +
  • Files - Documentation for all files
  • +
  • Modules - Documentation for all modules
  • +
  • Examples - Documentation for all examples
  • +
+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/index.xml b/docs/docs/api/index.xml new file mode 100644 index 00000000..708b5f95 --- /dev/null +++ b/docs/docs/api/index.xml @@ -0,0 +1,11 @@ + + + + API Reference on LDS C&E + //localhost:62388/docs/api/ + Recent content in API Reference on LDS C&E + Hugo + en + + + diff --git a/docs/docs/api/modules/group__control__masks/index.html b/docs/docs/api/modules/group__control__masks/index.html index a9d1027c..a2426a0a 100644 --- a/docs/docs/api/modules/group__control__masks/index.html +++ b/docs/docs/api/modules/group__control__masks/index.html @@ -4,19 +4,19 @@ - - - - - - - + + + + + + + Control Mode Bit Masks | LDS C&E - + + + + + + +
+ + +
+
+ +
+ + + std + + +
+ + + + + + +
+ + + +

+ std + # +

+
+
+

Updated on 3 April 2025 at 13:48:30 EDT

+
+ + + +
+ +
+ + + + + +
+ + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + diff --git a/docs/docs/api/pages/index.html b/docs/docs/api/pages/index.html index 5294f06c..054fa5d1 100644 --- a/docs/docs/api/pages/index.html +++ b/docs/docs/api/pages/index.html @@ -3,18 +3,24 @@ - - - - - + + + + + + + Pages | LDS C&E - + 0. May - // want to revisit, but I am going to force it to be zero unless a - // situation arises that argues for keeping the above. - dv_ref_.zeros(); - - dv_ = dv_ref_; // nominally-optimal. - dv_ -= Kc_ * (sys_.x() - x_ref_); // instantaneous state error - dv_ -= Kc_u_ * (v_ - v_ref_); // penalty on amp u (rel to ref) - - if (control_type_ & kControlTypeIntY) { - // TODO(mfbolus): one approach to protection against integral windup - // would be to not integrate error when control signal saturated: - - // if(!uSaturated) - int_e_ += (sys_.cx() - cx_ref_) * sys_.dt(); // integrated error - dv_ -= Kc_inty_ * int_e_; // control for integrated error - } - - // update the control - v_ += dv_; - } else { - v_ = v_ref_; // nominally-optimal. - v_ -= Kc_ * (sys_.x() - x_ref_); // instantaneous state error - - if (control_type_ & kControlTypeIntY) { - // TODO(mfbolus): one approach to protection against integral windup - // would be to not integrate error when control signal saturated: - - // if (!uSaturated) - int_e_ += (sys_.cx() - cx_ref_) * sys_.dt(); // integrated error - v_ -= Kc_inty_ * int_e_; // control for integrated error - } - } - - // convert back to control voltage u[=]V - u_ = v_ / sys_.g(); - } // else do nothing until lock is low - } else { // if not control - // feed through u_ref in open loop - u_ = u_ref_ % g_design_ / sys_.g(); - v_ = sys_.g() % u_; - u_ref_.zeros(); - int_e_.zeros(); - int_e_awu_adjust_.zeros(); - u_sat_.zeros(); - } // ends do_control - - // enforce box constraints (and antiwindup) - AntiWindup(); - - // add noise to input? - // The value for u that is *returned* to user after addition of any noise, - // while keeping controller/estimator blind to this addition. - u_return_ = u_; - if ((sigma_u_noise > 0.0) && (do_control && !do_lock_control)) { - u_return_ += sigma_u_noise * Vector(sys_.n_u(), fill::randn); - Limit(u_return_, u_lb_, u_ub_); - }; - - // For next time step: - u_ref_prev_ = u_ref_; - do_control_prev_ = do_control; - do_lock_control_prev_ = do_lock_control; -} // CalcControl - -template -inline void Controller::CalcSteadyStateSetPoint() { - // Linearly-constrained least squares (ls). - // - // _reference: - // Boyd & Vandenberghe (2018) Introduction to Applied Linear Algebra - // - Matrix a_ls = - join_horiz(sys_.C(), Matrix(sys_.n_y(), sys_.n_u(), fill::zeros)); - Vector b_ls = cx_ref_; - Matrix c_ls = join_horiz(sys_.A() - Matrix(sys_.n_x(), sys_.n_x(), fill::eye), - sys_.B() * arma::diagmat(sys_.g())); - Vector d_ls = -sys_.m0(); - if (control_type_ & kControlTypeAdaptM) { - d_ls = -sys_.m(); // adapt setpoint calc with disturbance? - } - - Matrix a_ls_t = a_ls.t(); // TODO(mfbolus): not sure why but causes seg - // fault if I do not do this. - Matrix phi_ls = - join_vert(join_horiz(2 * a_ls_t * a_ls, c_ls.t()), - join_horiz(c_ls, Matrix(sys_.n_x(), sys_.n_x(), fill::zeros))); - // TODO(mfbolus): should be actual inverse, rather than pseudo-inverse: - Matrix inv_phi = pinv(phi_ls); - Vector xulam = inv_phi * join_vert(2 * a_ls_t * b_ls, d_ls); - x_ref_ = xulam.subvec(0, sys_.n_x() - 1); - u_ref_ = xulam.subvec(sys_.n_x(), sys_.n_x() + sys_.n_u() - 1); - cx_ref_ = sys_.C() * x_ref_; -} // CalcSteadyStateSetPoint - -template -void Controller::AntiWindup() { - u_saturated_ = false; - u_sat_ = u_; - - // limit u and flag whether saturated - for (size_t k = 0; k < u_.n_elem; k++) { - if (u_[k] < u_lb_) { - u_sat_[k] = u_lb_; - u_saturated_ = true; - } - - if (u_[k] > u_ub_) { - u_sat_[k] = u_ub_; - u_saturated_ = true; - } - } - - if ((control_type_ & kControlTypeIntY) && (tau_awu_ < lds::kInf)) { - // one-step back-calculation (calculate intE for u=u_sat) - // (Astroem, Rundqwist 1989 warn against using this...) - // int_e_awu_adjust_ = - // solve(Kc_inty_, (u_ - u_sat_)); // pinv(Kc_inty) * (u-uSat); - - // gradual: see Astroem, Rundqwist 1989 - // this is a fudge for doing MIMO gradual - // n.b., went ahead and multiplied 1/T by dt so don't have to do that here. - int_e_awu_adjust_ = - k_awu_ * (sign(Kc_inty_).t() / sys_.n_u()) * (u_ - u_sat_); - // int_e_awu_adjust_ = k_awu_ * (u_-u_sat_); - - int_e_ += int_e_awu_adjust_; - } - - // set u to saturated version - u_ = u_sat_; -} - -template -void Controller::InitVars(size_t control_type) { - // initialize to default values - u_ref_ = Vector(sys_.n_u(), fill::zeros); - u_ref_prev_ = Vector(sys_.n_u(), fill::zeros); - x_ref_ = Vector(sys_.n_x(), fill::zeros); - y_ref_ = Vector(sys_.n_y(), fill::zeros); - cx_ref_ = Vector(sys_.n_y(), fill::zeros); - - u_ = Vector(sys_.n_u(), fill::zeros); - u_return_ = Vector(sys_.n_u(), fill::zeros); - u_sat_ = Vector(sys_.n_u(), fill::zeros); - - // Might not need all these, so zero elements until later. - Kc_ = Matrix(sys_.n_u(), sys_.n_x(), fill::zeros); - Kc_u_ = Matrix(0, 0, fill::zeros); - Kc_inty_ = Matrix(0, 0, fill::zeros); - - g_design_ = sys_.g(); // by default, same as model - dv_ = Vector(sys_.n_u(), fill::zeros); - v_ = Vector(sys_.n_u(), fill::zeros); - du_ref_ = Vector(sys_.n_u(), fill::zeros); - dv_ref_ = Vector(sys_.n_u(), fill::zeros); - v_ref_ = Vector(sys_.n_u(), fill::zeros); - - int_e_ = Vector(0, fill::zeros); - int_e_awu_adjust_ = Vector(0, fill::zeros); - - set_control_type(control_type); -} - -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_ctrl.h +summary: Controller. + +--- + +# ldsCtrlEst_h/lds_ctrl.h + +Controller. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1_controller/)** | + +## Detailed Description + + + +This file declares the type for control of a linear dynamical system ([lds::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1_controller/)). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_control.h - Controller -----------------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_CTRL_H +#define LDSCTRLEST_LDS_CTRL_H + +// namespace +#include "lds.h" +// system type +#include "lds_sys.h" + +namespace lds { + +template +class Controller { + static_assert(std::is_base_of::value, + "System must be derived from lds::System type."); + + public: + Controller() = default; + + Controller(const System& sys, data_t u_lb, data_t u_ub, + size_t control_type = 0); + + Controller(System&& sys, data_t u_lb, data_t u_ub, size_t control_type = 0); + + const Vector& Control(const Vector& z, bool do_control = true, + bool do_lock_control = false, + data_t sigma_soft_start = 0, data_t sigma_u_noise = 0, + bool do_reset_at_control_onset = true); + + const Vector& ControlOutputReference(const Vector& z, bool do_control = true, + bool do_estimation = true, + bool do_lock_control = false, + data_t sigma_soft_start = 0, + data_t sigma_u_noise = 0, + bool do_reset_at_control_onset = true); + + // get methods: + const System& sys() const { return sys_; }; + const Matrix& Kc() const { return Kc_; }; + const Matrix& Kc_inty() const { return Kc_inty_; }; + const Matrix& Kc_u() const { return Kc_u_; }; + const Vector& g_design() const { return g_design_; }; + const Vector& u_ref() const { return u_ref_; }; + const Vector& x_ref() const { return x_ref_; }; + const Vector& y_ref() const { return y_ref_; }; + size_t control_type() const { return control_type_; }; + data_t tau_awu() const { return tau_awu_; }; + data_t u_lb() const { return u_lb_; }; + data_t u_ub() const { return u_ub_; }; + + // set methods + void set_sys(const System& sys) { + bool does_match = sys_.n_u() == sys.n_u(); + does_match = does_match && (sys_.n_x() == sys.n_x()); + does_match = does_match && (sys_.n_y() == sys.n_y()); + if (does_match) { + sys_ = sys; + } else { + throw std::runtime_error( + "new system argument to `set_sys` does not match dimensionality of " + "existing system"); + } + }; + void set_g_design(const Vector& g_design) { Reassign(g_design_, g_design); }; + void set_u_ref(const Vector& u_ref) { Reassign(u_ref_, u_ref); }; + void set_x_ref(const Vector& x_ref) { + Reassign(x_ref_, x_ref); + cx_ref_ = sys_.C() * x_ref_; + }; + + // y_ref needs to be handled differently depending on output fn. + // (need to populate cx_ref_ too, which depends on output fn) + virtual void set_y_ref(const Vector& y_ref) { Reassign(y_ref_, y_ref); }; + + void set_Kc(const Matrix& Kc) { Reassign(Kc_, Kc); }; + void set_Kc_inty(const Matrix& Kc_inty) { Reassign(Kc_inty_, Kc_inty); }; + void set_Kc_u(const Matrix& Kc_u) { Reassign(Kc_u_, Kc_u); }; + void set_tau_awu(data_t tau) { + tau_awu_ = tau; + k_awu_ = sys_.dt() / tau_awu_; + }; + + void set_control_type(size_t control_type); + + // There is no reason u_lb/ub should not be public, but making set methods + // anyway. + void set_u_lb(data_t u_lb) { u_lb_ = u_lb; }; + + void set_u_ub(data_t u_ub) { u_ub_ = u_ub; }; + + void Reset() { + sys_.Reset(); + u_ref_.zeros(); + u_ref_prev_.zeros(); + int_e_.zeros(); + int_e_awu_adjust_.zeros(); + u_sat_.zeros(); + u_saturated_ = false; + t_since_control_onset_ = 0.0; + }; + + void Print() { + sys_.Print(); + std::cout << "g_design : " << g_design_ << "\n"; + std::cout << "u_lb : " << u_lb_ << "\n"; + std::cout << "u_ub : " << u_ub_ << "\n"; + }; + + protected: + System sys_; + + Vector u_; + Vector u_return_; + + Vector g_design_; + + // reference signals + Vector u_ref_; + // create no set method for this: + Vector u_ref_prev_; + Vector x_ref_; + Vector y_ref_; + Vector cx_ref_; + + // Controller gains + Matrix Kc_; + Matrix + Kc_u_; + Matrix Kc_inty_; + + // control after g inversion + // do not need set methods for these. + Vector du_ref_; + Vector dv_ref_; + Vector v_ref_; + Vector dv_; + Vector v_; + + // integral error + // do not need set method for this + Vector int_e_; + Vector int_e_awu_adjust_; + Vector u_sat_; + + bool do_control_prev_ = false; + bool do_lock_control_prev_ = false; + + // whether the g of system has become inverted from what you think it is + // (gain_ref) + bool u_saturated_ = + false; + + // should be safe to have references here bc nothing needs to be done + // (like reset vars) when it changes... + data_t u_lb_{}; + data_t u_ub_{}; + + data_t tau_awu_{}; + data_t k_awu_ = 0; + + data_t t_since_control_onset_ = 0; + size_t control_type_{}; + + private: + void CalcControl(bool do_control = true, bool do_estimation = true, + bool do_lock_control = false, data_t sigma_soft_start = 0, + data_t sigma_u_noise = 0, + bool do_reset_at_control_onset = true); + + void CalcSteadyStateSetPoint(); + + void AntiWindup(); + + void InitVars(size_t control_type); +}; + +// Implement the above: + +template +inline Controller::Controller(const System& sys, data_t u_lb, + data_t u_ub, size_t control_type) + : sys_(sys), + u_lb_(u_lb), + u_ub_(u_ub), + tau_awu_(lds::kInf) { + InitVars(control_type); +} + +template +inline Controller::Controller(System&& sys, data_t u_lb, data_t u_ub, + size_t control_type) + : sys_(std::move(sys)), + u_lb_(u_lb), + u_ub_(u_ub), + tau_awu_(lds::kInf) { + InitVars(control_type); +} + +template +inline void Controller::set_control_type(size_t control_type) { + if (control_type_ == control_type) { + return; + } + + // creating a blank slate... + control_type_ = 0; + Kc_inty_.zeros(0, 0); + Kc_u_.zeros(0, 0); + int_e_.zeros(0, 0); + int_e_awu_adjust_.zeros(0, 0); + + // controller was designed to minimize integral error + if (control_type & kControlTypeIntY) { + Kc_inty_.zeros(sys_.n_u(), sys_.n_y()); + int_e_.zeros(sys_.n_y()); + int_e_awu_adjust_.zeros(sys_.n_u()); + control_type_ = control_type_ | kControlTypeIntY; + } + + // controller was designed to minimize deltaU + // (i.e. state augmented with u) + if (control_type & kControlTypeDeltaU) { + Kc_u_.zeros(sys_.n_u(), sys_.n_u()); + control_type_ = control_type_ | kControlTypeDeltaU; + } + + // whether to adapt set point calculate with (re-estimated) process + // disturbance (m) + if (control_type & kControlTypeAdaptM) { + if (sys_.do_adapt_m) // only if adapting m... + { + control_type_ = control_type_ | kControlTypeAdaptM; + } + } +} // set_control_type + +template +inline const Vector& Controller::Control( + const Vector& z, bool do_control, bool do_lock_control, + data_t sigma_soft_start, data_t sigma_u_noise, + bool do_reset_at_control_onset) { + // update state estimates, given latest measurement + sys_.Filter(u_, z); + + bool do_estimation = true; // always have estimator on in this case + + // calculate control signal + CalcControl(do_control, do_estimation, do_lock_control, sigma_soft_start, + sigma_u_noise, do_reset_at_control_onset); + + return u_return_; +} + +template +inline const Vector& Controller::ControlOutputReference( + const Vector& z, bool do_control, bool do_estimation, bool do_lock_control, + data_t sigma_soft_start, data_t sigma_u_noise, + bool do_reset_at_control_onset) { + // update state estimates, given latest measurement + if (do_estimation) { + sys_.Filter(u_, z); + } else { + sys_.f(u_); + } + + // calculate the set point + // solves for u_ref and x_ref when output is at y_ref at steady state. + if (do_control) { + CalcSteadyStateSetPoint(); + } + + // calculate control signal + CalcControl(do_control, do_estimation, do_lock_control, sigma_soft_start, + sigma_u_noise, do_reset_at_control_onset); + + return u_return_; +} + +template +inline void Controller::CalcControl(bool do_control, bool do_estimation, + bool do_lock_control, + data_t sigma_soft_start, + data_t sigma_u_noise, + bool do_reset_at_control_onset) { + if (do_control && do_estimation) { + if (!do_control_prev_) { + if (do_reset_at_control_onset) { + Reset(); + } + t_since_control_onset_ = 0.0; + } else { + t_since_control_onset_ += sys_.dt(); + } + + // enforce softstart on control vars. + if (sigma_soft_start > 0) { + // half-Gaussian soft-start scaling factor + data_t soft_start_sf = 1 - exp(-pow(t_since_control_onset_, 2) / + (2 * pow(sigma_soft_start, 2))); + u_ref_ *= soft_start_sf; + // TODO(mfbolus): May be appropriate to soft-start x_ref, y_ref too + // x_ref_ *= soft_start_sf; + // cx_ref_ *= soft_start_sf; + // y_ref_ *= soft_start_sf; + } + + if (!do_lock_control) { + // first do u -> v change of vars. (v = g.*u) + // e.g., convert into physical units (e.g., v[=] mW/mm2 rather than driver + // control voltage u[=]V) + v_ref_ = g_design_ % u_ref_; + + // Given FB, calc. the change in control + if (control_type_ & kControlTypeDeltaU) { + // if control designed to minimize not u but deltaU (i.e. state aug with + // u): + + // TODO(mfbolus): Commented out for now. See note below. + // du_ref_ = u_ref_ - u_ref_prev_; + // dv_ref_ = g_design_ % du_ref_; + + // TODO(mfbolus): Assuming users want *smooth* control signals if using + // kControlTypeDeltaU, it should be the case that dv_ref_ is --> 0. May + // want to revisit, but I am going to force it to be zero unless a + // situation arises that argues for keeping the above. + dv_ref_.zeros(); + + dv_ = dv_ref_; // nominally-optimal. + dv_ -= Kc_ * (sys_.x() - x_ref_); // instantaneous state error + dv_ -= Kc_u_ * (v_ - v_ref_); // penalty on amp u (rel to ref) + + if (control_type_ & kControlTypeIntY) { + // TODO(mfbolus): one approach to protection against integral windup + // would be to not integrate error when control signal saturated: + + // if(!uSaturated) + int_e_ += (sys_.cx() - cx_ref_) * sys_.dt(); // integrated error + dv_ -= Kc_inty_ * int_e_; // control for integrated error + } + + // update the control + v_ += dv_; + } else { + v_ = v_ref_; // nominally-optimal. + v_ -= Kc_ * (sys_.x() - x_ref_); // instantaneous state error + + if (control_type_ & kControlTypeIntY) { + // TODO(mfbolus): one approach to protection against integral windup + // would be to not integrate error when control signal saturated: + + // if (!uSaturated) + int_e_ += (sys_.cx() - cx_ref_) * sys_.dt(); // integrated error + v_ -= Kc_inty_ * int_e_; // control for integrated error + } + } + + // convert back to control voltage u[=]V + u_ = v_ / sys_.g(); + } // else do nothing until lock is low + } else { // if not control + // feed through u_ref in open loop + u_ = u_ref_ % g_design_ / sys_.g(); + v_ = sys_.g() % u_; + u_ref_.zeros(); + int_e_.zeros(); + int_e_awu_adjust_.zeros(); + u_sat_.zeros(); + } // ends do_control + + // enforce box constraints (and antiwindup) + AntiWindup(); + + // add noise to input? + // The value for u that is *returned* to user after addition of any noise, + // while keeping controller/estimator blind to this addition. + u_return_ = u_; + if ((sigma_u_noise > 0.0) && (do_control && !do_lock_control)) { + u_return_ += sigma_u_noise * Vector(sys_.n_u(), fill::randn); + Limit(u_return_, u_lb_, u_ub_); + }; + + // For next time step: + u_ref_prev_ = u_ref_; + do_control_prev_ = do_control; + do_lock_control_prev_ = do_lock_control; +} // CalcControl + +template +inline void Controller::CalcSteadyStateSetPoint() { + // Linearly-constrained least squares (ls). + // + // _reference: + // Boyd & Vandenberghe (2018) Introduction to Applied Linear Algebra + // + Matrix a_ls = + join_horiz(sys_.C(), Matrix(sys_.n_y(), sys_.n_u(), fill::zeros)); + Vector b_ls = cx_ref_; + Matrix c_ls = join_horiz(sys_.A() - Matrix(sys_.n_x(), sys_.n_x(), fill::eye), + sys_.B() * arma::diagmat(sys_.g())); + Vector d_ls = -sys_.m0(); + if (control_type_ & kControlTypeAdaptM) { + d_ls = -sys_.m(); // adapt setpoint calc with disturbance? + } + + Matrix a_ls_t = a_ls.t(); // TODO(mfbolus): not sure why but causes seg + // fault if I do not do this. + Matrix phi_ls = + join_vert(join_horiz(2 * a_ls_t * a_ls, c_ls.t()), + join_horiz(c_ls, Matrix(sys_.n_x(), sys_.n_x(), fill::zeros))); + // TODO(mfbolus): should be actual inverse, rather than pseudo-inverse: + Matrix inv_phi = pinv(phi_ls); + Vector xulam = inv_phi * join_vert(2 * a_ls_t * b_ls, d_ls); + x_ref_ = xulam.subvec(0, sys_.n_x() - 1); + u_ref_ = xulam.subvec(sys_.n_x(), sys_.n_x() + sys_.n_u() - 1); + cx_ref_ = sys_.C() * x_ref_; +} // CalcSteadyStateSetPoint + +template +void Controller::AntiWindup() { + u_saturated_ = false; + u_sat_ = u_; + + // limit u and flag whether saturated + for (size_t k = 0; k < u_.n_elem; k++) { + if (u_[k] < u_lb_) { + u_sat_[k] = u_lb_; + u_saturated_ = true; + } + + if (u_[k] > u_ub_) { + u_sat_[k] = u_ub_; + u_saturated_ = true; + } + } + + if ((control_type_ & kControlTypeIntY) && (tau_awu_ < lds::kInf)) { + // one-step back-calculation (calculate intE for u=u_sat) + // (Astroem, Rundqwist 1989 warn against using this...) + // int_e_awu_adjust_ = + // solve(Kc_inty_, (u_ - u_sat_)); // pinv(Kc_inty) * (u-uSat); + + // gradual: see Astroem, Rundqwist 1989 + // this is a fudge for doing MIMO gradual + // n.b., went ahead and multiplied 1/T by dt so don't have to do that here. + int_e_awu_adjust_ = + k_awu_ * (sign(Kc_inty_).t() / sys_.n_u()) * (u_ - u_sat_); + // int_e_awu_adjust_ = k_awu_ * (u_-u_sat_); + + int_e_ += int_e_awu_adjust_; + } + + // set u to saturated version + u_ = u_sat_; +} + +template +void Controller::InitVars(size_t control_type) { + // initialize to default values + u_ref_ = Vector(sys_.n_u(), fill::zeros); + u_ref_prev_ = Vector(sys_.n_u(), fill::zeros); + x_ref_ = Vector(sys_.n_x(), fill::zeros); + y_ref_ = Vector(sys_.n_y(), fill::zeros); + cx_ref_ = Vector(sys_.n_y(), fill::zeros); + + u_ = Vector(sys_.n_u(), fill::zeros); + u_return_ = Vector(sys_.n_u(), fill::zeros); + u_sat_ = Vector(sys_.n_u(), fill::zeros); + + // Might not need all these, so zero elements until later. + Kc_ = Matrix(sys_.n_u(), sys_.n_x(), fill::zeros); + Kc_u_ = Matrix(0, 0, fill::zeros); + Kc_inty_ = Matrix(0, 0, fill::zeros); + + g_design_ = sys_.g(); // by default, same as model + dv_ = Vector(sys_.n_u(), fill::zeros); + v_ = Vector(sys_.n_u(), fill::zeros); + du_ref_ = Vector(sys_.n_u(), fill::zeros); + dv_ref_ = Vector(sys_.n_u(), fill::zeros); + v_ref_ = Vector(sys_.n_u(), fill::zeros); + + int_e_ = Vector(0, fill::zeros); + int_e_awu_adjust_ = Vector(0, fill::zeros); + + set_control_type(control_type); +} + +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__fit_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__fit_8h.md index f1642701..f6259764 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__fit_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__fit_8h.md @@ -1,151 +1,151 @@ ---- -title: ldsCtrlEst_h/lds_fit.h -summary: LDS base fit type. - ---- - -# ldsCtrlEst_h/lds_fit.h - -LDS base fit type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1fit/)**
LDS [Fit]() Type. | - -## Detailed Description - - - -This file declares and partially defines the base fit type for a linear dynamical system. It is expounded upon by variants with Gaussian and Poisson observation assumptions for fitting. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_fit.h - Fit Type for LDS ---------------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDS_FIT_HPP -#define LDS_FIT_HPP - -// namespace -#include "lds.h" -#include "lds_uniform_mats.h" - -namespace lds { -class Fit { - public: - Fit() = default; - Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt); - - virtual ~Fit() = default; - - // get methods - size_t n_u() const { return n_u_; }; - size_t n_x() const { return n_x_; }; - size_t n_y() const { return n_y_; }; - data_t dt() const { return dt_; }; - const Matrix& A() const { return A_; }; - const Matrix& B() const { return B_; }; - const Vector& g() const { return g_; }; - const Vector& m() const { return m_; }; - const Matrix& Q() const { return Q_; }; - const Vector& x0() const { return x0_; }; - const Matrix& P0() const { return P0_; }; - const Matrix& C() const { return C_; }; - const Vector& d() const { return d_; }; - // gets measurement noise - virtual const Matrix& R() const = 0; - - // set methods (e.g., seeding initial fit values) - void set_A(const Matrix& A) { Reassign(A_, A); }; - void set_B(const Matrix& B) { Reassign(B_, B); }; - void set_g(const Vector& g) { Reassign(g_, g); }; - void set_m(const Vector& m) { Reassign(m_, m); }; - void set_Q(const Matrix& Q) { - Reassign(Q_, Q); - ForceSymPD(Q_); - }; - virtual void set_R(const Matrix& R) = 0; - void set_x0(const Vector& x0) { Reassign(x0_, x0); }; - void set_P0(const Matrix& P0) { - Reassign(P0_, P0); - ForceSymPD(P0_); - }; - void set_C(const Matrix& C) { Reassign(C_, C); }; - void set_d(const Vector& d) { Reassign(d_, d); }; - - View f(Matrix& x, const Matrix& u, size_t t) { - x.col(t) = A_ * x.col(t - 1) + B_ * (g_ % u.col(t - 1)) + m_; - return x.col(t); - }; - - View f(Matrix& x_pre, const Matrix& x_post, const Matrix& u, size_t t) { - x_pre.col(t) = A_ * x_post.col(t - 1) + B_ * (g_ % u.col(t - 1)) + m_; - return x_pre.col(t); - }; - - virtual View h(Matrix& y, const Matrix& x, size_t t) = 0; - - protected: - data_t dt_{}; - - // Dynamics - Matrix A_; - Matrix B_; - Vector g_; - Vector m_; - Matrix Q_; - - // Output - Matrix C_; - Vector d_; - Matrix R_; - - // initial conditions - Vector x0_; - Matrix P0_; - - size_t n_u_{}; - size_t n_x_{}; - size_t n_y_{}; -}; - -} // namespace lds -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_fit.h +summary: LDS base fit type. + +--- + +# ldsCtrlEst_h/lds_fit.h + +LDS base fit type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1_fit/)**
LDS [Fit]() Type. | + +## Detailed Description + + + +This file declares and partially defines the base fit type for a linear dynamical system. It is expounded upon by variants with Gaussian and Poisson observation assumptions for fitting. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_fit.h - Fit Type for LDS ---------------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDS_FIT_HPP +#define LDS_FIT_HPP + +// namespace +#include "lds.h" +#include "lds_uniform_mats.h" + +namespace lds { +class Fit { + public: + Fit() = default; + Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt); + + virtual ~Fit() = default; + + // get methods + size_t n_u() const { return n_u_; }; + size_t n_x() const { return n_x_; }; + size_t n_y() const { return n_y_; }; + data_t dt() const { return dt_; }; + const Matrix& A() const { return A_; }; + const Matrix& B() const { return B_; }; + const Vector& g() const { return g_; }; + const Vector& m() const { return m_; }; + const Matrix& Q() const { return Q_; }; + const Vector& x0() const { return x0_; }; + const Matrix& P0() const { return P0_; }; + const Matrix& C() const { return C_; }; + const Vector& d() const { return d_; }; + // gets measurement noise + virtual const Matrix& R() const = 0; + + // set methods (e.g., seeding initial fit values) + void set_A(const Matrix& A) { Reassign(A_, A); }; + void set_B(const Matrix& B) { Reassign(B_, B); }; + void set_g(const Vector& g) { Reassign(g_, g); }; + void set_m(const Vector& m) { Reassign(m_, m); }; + void set_Q(const Matrix& Q) { + Reassign(Q_, Q); + ForceSymPD(Q_); + }; + virtual void set_R(const Matrix& R) = 0; + void set_x0(const Vector& x0) { Reassign(x0_, x0); }; + void set_P0(const Matrix& P0) { + Reassign(P0_, P0); + ForceSymPD(P0_); + }; + void set_C(const Matrix& C) { Reassign(C_, C); }; + void set_d(const Vector& d) { Reassign(d_, d); }; + + View f(Matrix& x, const Matrix& u, size_t t) { + x.col(t) = A_ * x.col(t - 1) + B_ * (g_ % u.col(t - 1)) + m_; + return x.col(t); + }; + + View f(Matrix& x_pre, const Matrix& x_post, const Matrix& u, size_t t) { + x_pre.col(t) = A_ * x_post.col(t - 1) + B_ * (g_ % u.col(t - 1)) + m_; + return x_pre.col(t); + }; + + virtual View h(Matrix& y, const Matrix& x, size_t t) = 0; + + protected: + data_t dt_{}; + + // Dynamics + Matrix A_; + Matrix B_; + Vector g_; + Vector m_; + Matrix Q_; + + // Output + Matrix C_; + Vector d_; + Matrix R_; + + // initial conditions + Vector x0_; + Matrix P0_; + + size_t n_u_{}; + size_t n_x_{}; + size_t n_y_{}; +}; + +} // namespace lds +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__fit__em_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__fit__em_8h.md index ae2dbecb..c3c296f9 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__fit__em_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__fit__em_8h.md @@ -1,634 +1,634 @@ ---- -title: ldsCtrlEst_h/lds_fit_em.h -summary: subspace identification - ---- - -# ldsCtrlEst_h/lds_fit_em.h - -subspace identification [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::EM](/lds-ctrl-est/docs/api/classes/classlds_1_1em/)** | - -## Detailed Description - - - -This file declares the type for fitting a linear dynamical system by expectation-maximization ([lds::EM](/lds-ctrl-est/docs/api/classes/classlds_1_1em/)). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_fit_em.h - EM Fit ----------------------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_EMAX_H -#define LDSCTRLEST_LDS_EMAX_H - -#include "lds_fit.h" - -namespace lds { - -template -class EM { - static_assert(std::is_base_of::value, - "Fit must be derived from lds::Fit type."); - - public: - EM() = default; - - EM(size_t n_x, data_t dt, UniformMatrixList&& u_train, - UniformMatrixList&& z_train); - - EM(const Fit& fit0, UniformMatrixList&& u_train, - UniformMatrixList&& z_train); - - virtual ~EM() = default; - - const Fit& Run(bool calc_dynamics = true, bool calc_Q = true, - bool calc_init = true, bool calc_output = true, - bool calc_measurement = true, size_t max_iter = 100, - data_t tol = 1e-2); - - std::tuple, UniformMatrixList> - ReturnData() { - auto tuple = std::make_tuple(std::move(u_), std::move(z_)); - // auto tuple = std::make_tuple(u_, z_); - u_ = UniformMatrixList(); - z_ = UniformMatrixList(); - return tuple; - } - - const std::vector& x() const { return x_; }; - const std::vector& y() const { return y_; }; - - const Matrix& sum_E_x_t_x_t() const { return sum_E_x_t_x_t_; }; - const Matrix& sum_E_xu_tm1_xu_tm1() const { return sum_E_xu_tm1_xu_tm1_; }; - const Matrix& sum_E_xu_t_xu_tm1() const { return sum_E_xu_t_xu_tm1_; }; - size_t n_t_tot() { return n_t_tot_; } - - const Vector& theta() const { return theta_; }; - - protected: - void Expectation(bool force_common_initial = false); - - void Maximization(bool calc_dynamics = true, bool calc_Q = true, - bool calc_init = false, bool calc_output = false, - bool calc_measurement = false); - - void MaximizeDynamics(); - void MaximizeQ(); - void MaximizeInitial(); - virtual void MaximizeOutput() = 0; - virtual void MaximizeMeasurement() = 0; - - void Smooth(bool force_common_initial); - - virtual void RecurseKe(Matrix& Ke, Cube& P_pre, Cube& P_post, size_t t) = 0; - - void Reset(); - - void InitVars(); - - Vector UpdateTheta(); - - // input/output training data - UniformMatrixList u_; - UniformMatrixList z_; - std::vector x_; - std::vector P_; - std::vector P_t_tm1_; - std::vector y_; - Matrix diag_y_; - - // expectations calculated in E-step - Matrix sum_E_x_t_x_t_; - Matrix sum_E_xu_tm1_xu_tm1_; - Matrix sum_E_xu_t_xu_tm1_; - - Fit fit_; - Vector theta_; - - data_t dt_{}; - size_t n_u_{}; - size_t n_x_{}; - size_t n_y_{}; - size_t n_trials_{}; - std::vector n_t_; - size_t n_t_tot_{}; -}; - -template -EM::EM(size_t n_x, data_t dt, UniformMatrixList&& u_train, - UniformMatrixList&& z_train) { - n_u_ = u_train.at(0).n_rows; - n_y_ = z_train.at(0).n_rows; - fit_ = Fit(n_u_, n_x, n_y_, dt); - u_ = std::move(u_train); - z_ = std::move(z_train); - InitVars(); -} - -template -EM::EM(const Fit& fit0, UniformMatrixList&& u_train, - UniformMatrixList&& z_train) { - // make sure fit dims match I/O data - if (fit0.n_u() != u_train.at(0).n_rows) { - throw std::runtime_error( - "Initial fit and input training data have inconsistent dimensions"); - } - if (fit0.n_y() != z_train.at(0).n_rows) { - throw std::runtime_error( - "Initial fit and output training data have inconsistent dimensions"); - } - - fit_ = fit0; - u_ = std::move(u_train); - z_ = std::move(z_train); - - InitVars(); -} - -template -void EM::InitVars() { - // check input/output data dimensions are consistent - if (z_.size() != u_.size()) { - throw std::runtime_error( - "I/O training data have different number of trials."); - } - n_trials_ = u_.size(); - - n_t_tot_ = 0; - n_t_ = std::vector(n_trials_); - for (size_t trial = 0; trial < n_trials_; trial++) { - if (z_.at(trial).n_cols != u_.at(trial).n_cols) { - throw std::runtime_error( - "I/O training data have different number of time steps."); - } - n_t_[trial] = u_.at(trial).n_cols; - n_t_tot_ += n_t_[trial]; - } - - n_u_ = fit_.n_u(); - n_x_ = fit_.n_x(); - n_y_ = fit_.n_y(); - dt_ = fit_.dt(); - - x_ = std::vector(n_trials_); - P_ = std::vector(n_trials_); - P_t_tm1_ = std::vector(n_trials_); - y_ = std::vector(n_trials_); - for (size_t trial = 0; trial < n_trials_; trial++) { - x_[trial] = Matrix(n_x_, n_t_[trial], fill::zeros); - P_[trial] = Cube(n_x_, n_x_, n_t_[trial], fill::zeros); - P_t_tm1_[trial] = Cube(n_x_, n_x_, n_t_[trial], fill::zeros); - y_[trial] = Matrix(n_y_, n_t_[trial], fill::zeros); - } - - diag_y_ = Matrix(n_y_, n_y_, fill::zeros); - - // covariances in expectation step - sum_E_x_t_x_t_ = Matrix(n_x_, n_x_, fill::zeros); - sum_E_xu_tm1_xu_tm1_ = Matrix(n_x_ + n_u_, n_x_ + n_u_, fill::zeros); - sum_E_xu_t_xu_tm1_ = Matrix(n_x_ + n_u_, n_x_ + n_u_, fill::zeros); -} - -template -const Fit& EM::Run(bool calc_dynamics, bool calc_Q, bool calc_init, - bool calc_output, bool calc_measurement, - size_t max_iter, data_t tol) { - Reset(); // to initial conditions - - size_t n_params = - 3 * n_x_ * n_x_ + n_x_ * n_u_ + n_x_ + n_y_ * n_x_ + n_y_ * n_y_; - Vector theta(n_params); - Vector theta_new(n_params); - data_t max_dtheta = 1; - - // if solving for initial conditions, allow them be varied. - // otherwise, freeze at provided values. - bool force_common_initial = !calc_init; - - // go until parameter convergence - for (size_t l = 0; l < max_iter; l++) { - theta_ = UpdateTheta(); - - std::cout << "Iteration " << l + 1 << "/" << max_iter << " ...\n"; - - Expectation(force_common_initial); - Maximization(calc_dynamics, calc_Q, calc_init, calc_output, - calc_measurement); - - // check convergence - theta_new = UpdateTheta(); - - Vector dtheta = abs(theta_new - theta_) / abs(theta_); - // some parameters could be zero... - arma::uvec ubi_finite = find_finite(dtheta); - - max_dtheta = max(dtheta.elem(ubi_finite)); - std::cout << "max dtheta: " << max_dtheta << "\n"; - if (max_dtheta < tol) { - std::cout << "Converged.\n"; - break; - } - - std::cout << "\n"; - } - - return fit_; -} - -template -void EM::Smooth(bool force_common_initial) { - Matrix k_e(n_x_, n_y_); // estimator gain - Cube k_backfilt; // back-filtering gains - - // TODO(mfbolus): this loop could be made parallel - for (size_t trial = 0; trial < z_.size(); trial++) { - Matrix x_pre(n_x_, n_t_[trial], fill::zeros); - Cube p_pre(n_x_, n_x_, n_t_[trial], fill::zeros); - Matrix x_post(n_x_, n_t_[trial], fill::zeros); - Cube p_post(n_x_, n_x_, n_t_[trial], fill::zeros); - - if (force_common_initial) // forces all trials to have same initial - // conditions. - { - x_[trial].col(0) = fit_.x0(); - P_[trial].slice(0) = fit_.P0(); - } - y_[trial].col(0) = fit_.C() * x_[trial].col(0) + fit_.d(); - - // This *should not* be necessary but make sure P is symmetric. - ForceSymPD(P_[trial].slice(0)); - - x_pre.col(0) = x_[trial].col(0); - p_pre.slice(0) = P_[trial].slice(0); - - x_post.col(0) = x_[trial].col(0); - p_post.slice(0) = P_[trial].slice(0); - - // filter - for (size_t t = 1; t < n_t_[trial]; t++) { - // predict - fit_.f(x_pre, x_post, u_.at(trial), t); - fit_.h(y_[trial], x_pre, t); - diag_y_.diag() = y_[trial].col(t); // TODO(mfbolus): change if parallel - - // update --> posterior estimation - RecurseKe(k_e, p_pre, p_post, t); - x_post.col(t) = - x_pre.col(t) + k_e * (z_.at(trial).col(t) - y_[trial].col(t)); - y_[trial].col(t) = fit_.C() * x_post.col(t) + fit_.d(); - } - - // backfilter -> Smoothed estimate - // Reference: - // Shumway et Stoffer (1982) - ForceSymPD(p_post.slice(n_t_[trial] - 1)); - k_backfilt = Cube(n_x_, n_x_, n_t_[trial], fill::zeros); - x_[trial].col(n_t_[trial] - 1) = x_post.col(n_t_[trial] - 1); - P_[trial].slice(n_t_[trial] - 1) = p_post.slice(n_t_[trial] - 1); - for (size_t t = (n_t_[trial] - 1); t > 0; t--) { - // TODO(mfmbolus): should not be necessary to force symm positive def - ForceSymPD(p_pre.slice(t)); - ForceSymPD(p_post.slice(t - 1)); - ForceSymPD(P_[trial].slice(t)); - k_backfilt.slice(t - 1) = - p_post.slice(t - 1) * fit_.A().t() * inv_sympd(p_pre.slice(t)); - x_[trial].col(t - 1) = - x_post.col(t - 1) + - k_backfilt.slice(t - 1) * (x_[trial].col(t) - x_pre.col(t)); - P_[trial].slice(t - 1) = - p_post.slice(t - 1) + k_backfilt.slice(t - 1) * - (P_[trial].slice(t) - p_pre.slice(t)) * - k_backfilt.slice(t - 1).t(); - } - - // do the same for P_t_tm1 - Matrix id(n_x_, n_x_, fill::eye); - P_t_tm1_[trial].slice(n_t_[trial] - 1) = - (id - k_e * fit_.C()) * fit_.A() * p_post.slice(n_t_[trial] - 2); - for (size_t t = (n_t_[trial] - 1); t > 1; t--) { - P_t_tm1_[trial].slice(t - 1) = - p_post.slice(t - 1) * k_backfilt.slice(t - 2).t() + - k_backfilt.slice(t - 1) * - (P_t_tm1_[trial].slice(t) - fit_.A() * p_post.slice(t - 1)) * - k_backfilt.slice(t - 2).t(); - } - - // finally, get smoothed estimate of output - for (size_t t = 0; t < n_t_[trial]; t++) { - fit_.h(y_[trial], x_[trial], t); - } // samps loop - } // trial loop -} // Smooth - -// template -// void EM::RecurseKe(Matrix& Ke, Cube& P_pre, Cube& P_post, size_t t) { -// // predict covar -// P_pre.slice(t) = fit_.A() * P_post.slice(t - 1) * fit_.A().t() + fit_.Q(); - -// // update Ke -// Ke = P_pre.slice(t) * fit_.C().t() * -// inv_sympd(fit_.C() * P_pre.slice(t) * fit_.C().t() + fit_.R()); - -// // update cov -// // Reference: Ghahramani et Hinton (1996) -// P_post.slice(t) = P_pre.slice(t) - Ke * fit_.C() * P_pre.slice(t); - -// // // n.b. for poisson : -// // P_pre.slice(t) = fit_.A() * P_post.slice(t - 1) * fit_.A().t() + -// fit_.Q(); -// // // update cov -// // P_post.slice(t) = pinv(pinv(P_pre.slice(t)) + fit_.C().t() * diag_y_ * -// // fit_.C()); -// // // update Ke -// // Ke = P_post.slice(t) * fit_.C(); -// } - -template -void EM::Expectation(bool force_common_initial) { - // calculate the mean/cov of state needed for maximizing E[pr(z|theta)] - Smooth(force_common_initial); - - // now get the various forms of sum(E[xx']) needed - // n.b. Going to start at t=1 rather than 0 bc most max terms need that. - // so really "n_t_tot_" is (n_t_tot_-1) - n_t_tot_ = 0; - sum_E_x_t_x_t_ = Matrix(n_x_, n_x_, fill::zeros); - sum_E_xu_tm1_xu_tm1_ = Matrix(n_x_ + n_u_, n_x_ + n_u_, fill::zeros); - sum_E_xu_t_xu_tm1_ = Matrix(n_x_ + n_u_, n_x_ + n_u_, fill::zeros); - - Vector xu_tm1(n_x_ + n_u_, fill::zeros); - Vector xu_t(n_x_ + n_u_, fill::zeros); - - for (size_t trial = 0; trial < z_.size(); trial++) { - for (size_t t = 1; t < n_t_[trial]; t++) { - // ------------ sum_E_x_t_x_t ------------ - sum_E_x_t_x_t_ += x_[trial].col(t) * x_[trial].col(t).t(); - sum_E_x_t_x_t_ += P_[trial].slice(t); - - // ------------ sum_E_xu_tm1_xu_tm1 ------------ - xu_tm1 = join_vert(x_[trial].col(t - 1), u_.at(trial).col(t - 1)); - sum_E_xu_tm1_xu_tm1_ += xu_tm1 * xu_tm1.t(); - sum_E_xu_tm1_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ - 1) += - P_[trial].slice(t - 1); - - // ------------ sum_E_xu_t_xu_tm1 ------------ - xu_t = join_vert(x_[trial].col(t), u_.at(trial).col(t)); - sum_E_xu_t_xu_tm1_ += xu_t * xu_tm1.t(); - sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ - 1) += - P_t_tm1_[trial].slice(t); - - n_t_tot_ += 1; - } // time - } // trial -} // Expectation - -template -void EM::Maximization(bool calc_dynamics, bool calc_Q, bool calc_init, - bool calc_output, bool calc_measurement) { - if (calc_output) { - MaximizeOutput(); - } - - if (calc_measurement) { - MaximizeMeasurement(); - } - - if (calc_dynamics) { - MaximizeDynamics(); - } - - if (calc_Q) { - MaximizeQ(); - } - - if (calc_init) { - MaximizeInitial(); - } -} // Maximization - -template -void EM::MaximizeDynamics() { - // Shumway, Stoffer (1982); Ghahgramani, Hinton (1996) - Matrix ab = sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ + n_u_ - 1) * - inv_sympd(sum_E_xu_tm1_xu_tm1_); - fit_.set_A(ab.submat(0, 0, n_x_ - 1, n_x_ - 1)); - fit_.set_B(ab.submat(0, n_x_, n_x_ - 1, n_x_ + n_u_ - 1)); - std::cout << "A_new[0]: " << fit_.A()[0] << "\n"; - std::cout << "B_new[0]: " << fit_.B()[0] << "\n"; -} - -template -void EM::MaximizeQ() { - // // Shumway, Stoffer (1982); Ghahgramani, Hinton (1996) - // View sum_e_x_t_xu_tm1 = - // sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ + n_u_ - 1); - // Matrix q = sum_E_x_t_x_t_ - sum_e_x_t_xu_tm1 * - // inv_sympd(sum_E_xu_tm1_xu_tm1_) * - // sum_e_x_t_xu_tm1.t(); - // q /= n_t_tot_; - - // this way is same as above iff dynamics were just updated: - // View sum_e_x_t_xu_tm1 = - // sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ + n_u_ - 1); - // Matrix ab = arma::join_horiz(fit_.A(), fit_.B()); - // Matrix q = sum_E_x_t_x_t_ - ab * sum_e_x_t_xu_tm1.t(); - // q /= n_t_tot_; - - // From scratch method: - // Q is covariance of the error between state and dynamics-predicted state - // (aka process noise) - // Q* = E[(x_t - Ax_{t-1} - Bu_{t-1})*(x_t - Ax_{t-1} - Bu_{t-1})'] - // t-1 terms: - View sum_e_x_tm1_x_tm1 = - sum_E_xu_tm1_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ - 1); - View sum_e_u_tm1_u_tm1 = - sum_E_xu_tm1_xu_tm1_.submat(n_x_, n_x_, n_x_ + n_u_ - 1, n_x_ + n_u_ - 1); - View sum_e_x_tm1_u_tm1 = - sum_E_xu_tm1_xu_tm1_.submat(0, n_x_, n_x_ - 1, n_x_ + n_u_ - 1); - - // t, t-1 terms: - View sum_e_x_t_x_tm1 = sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ - 1); - View sum_e_x_t_u_tm1 = - sum_E_xu_t_xu_tm1_.submat(0, n_x_, n_x_ - 1, n_x_ + n_u_ - 1); - - Matrix q = sum_E_x_t_x_t_; - q += fit_.A() * sum_e_x_tm1_x_tm1 * fit_.A().t(); - q -= sum_e_x_t_x_tm1 * fit_.A().t(); - q -= fit_.A() * sum_e_x_t_x_tm1.t(); - // input-related terms: - q += fit_.B() * sum_e_u_tm1_u_tm1 * fit_.B().t(); - q -= sum_e_x_t_u_tm1 * fit_.B().t(); - q -= fit_.B() * sum_e_x_t_u_tm1.t(); - q += fit_.A() * sum_e_x_tm1_u_tm1 * fit_.B().t(); - q += fit_.B() * sum_e_x_tm1_u_tm1.t() * fit_.A().t(); - q /= n_t_tot_; - - fit_.set_Q(q); - std::cout << "Q_new[0]: " << fit_.Q()[0] << "\n"; - // std::cout << "Q_new: \n" << fit_.Q() << "\n"; -} - -template -void EM::MaximizeInitial() { - Vector x0 = fit_.x0(); - x0.zeros(); - for (size_t trial = 0; trial < z_.size(); trial++) { - x0 += x_[trial].col(0); - } - x0 /= z_.size(); - std::cout << "x0_new[0]: " << x0[0] << "\n"; - - // always recalc P0 even if the initial state is fixed (at zero, for - // example) - Matrix e_var(n_x_, n_x_, fill::zeros); - for (size_t trial = 0; trial < z_.size(); trial++) { - e_var += (x_[trial].col(0) - x0) * (x_[trial].col(0) - x0).t(); - } - e_var /= z_.size(); - - // go ahead and subtract x0*x0' so don't have to below. - e_var -= x0 * x0.t(); - - // To get P0, going to get initial P_ per trial and average. - // (which might be wrong, but need a single number) - Matrix p0 = fit_.P0(); - p0.zeros(); - for (size_t trial = 0; trial < z_.size(); trial++) { - p0 += - (x_[trial].col(0) * x_[trial].col(0).t()) + P_[trial].slice(0) + e_var; - } - p0 /= z_.size(); - - fit_.set_P0(p0); - std::cout << "P0_new[0]: " << fit_.P0()[0] << "\n"; -} - -template -void EM::MaximizeOutput() { - // solve for C+d: - Matrix sum_zx(n_y_, n_x_ + 1, fill::zeros); - Vector x1(n_x_ + 1, fill::zeros); - x1[n_x_] = 1.0; // augment with one to solve for bias - Matrix sum_e_x1_x1(n_x_ + 1, n_x_ + 1, fill::zeros); - for (size_t trial = 0; trial < z_.size(); trial++) { - for (size_t t = 1; t < n_t_[trial]; t++) { - x1.subvec(0, n_x_ - 1) = x_[trial].col(t); - sum_zx += z_.at(trial).col(t) * x1.t(); - sum_e_x1_x1 += x1 * x1.t(); - sum_e_x1_x1.submat(0, 0, n_x_ - 1, n_x_ - 1) += P_[trial].slice(t); - } - } - Matrix cd = sum_zx * inv_sympd(sum_e_x1_x1); - fit_.set_C(cd.submat(0, 0, n_y_ - 1, n_x_ - 1)); - fit_.set_d(vectorise(cd.submat(0, n_x_, n_y_ - 1, n_x_))); - std::cout << "C_new[0]: " << fit_.C()[0] << "\n"; - std::cout << "d_new[0]: " << fit_.d()[0] << "\n"; -} - -template -void EM::MaximizeMeasurement() { - // Solve for measurement noise covar - size_t n_t_tot = 0; - // Ghahgramani, Hinton 1996: - Matrix sum_zz(n_y_, n_y_, fill::zeros); - Matrix sum_yz(n_y_, n_y_, fill::zeros); - for (size_t trial = 0; trial < z_.size(); trial++) { - for (size_t t = 1; t < n_t_[trial]; t++) { - sum_zz += z_.at(trial).col(t) * z_.at(trial).col(t).t(); - // Use Cnew: - sum_yz += - (fit_.C() * x_[trial].col(t) + fit_.d()) * z_.at(trial).col(t).t(); - n_t_tot += 1; - } - } - fit_.set_R((sum_zz - sum_yz) / n_t_tot); - std::cout << "R_new[0]: " << fit_.R()[0] << "\n"; -} - -template -void EM::Reset() { - // reset to initial conditions - for (size_t trial = 0; trial < n_trials_; trial++) { - x_[trial].col(0) = fit_.x0(); - P_[trial].slice(0) = fit_.P0(); - y_[trial].col(0) = fit_.C() * x_[trial].col(0) + fit_.d(); - } -} - -template -Vector EM::UpdateTheta() { - // TODO(mfbolus): This should include n_y_ more params for d. - size_t n_params = 3 * n_x_ * n_x_ + n_x_ * n_u_ + n_x_ + n_y_ * n_x_ + n_y_; - if (fit_.R().n_elem > 0) { - n_params += n_y_ * n_y_; - } - Vector theta(n_params); - - size_t idx_start = 0; - theta.subvec(idx_start, idx_start + n_x_ * n_x_ - 1) = vectorise(fit_.A()); - idx_start += n_x_ * n_x_; - theta.subvec(idx_start, idx_start + n_x_ * n_u_ - 1) = vectorise(fit_.B()); - idx_start += n_x_ * n_u_; - theta.subvec(idx_start, idx_start + n_x_ * n_x_ - 1) = vectorise(fit_.Q()); - idx_start += n_x_ * n_x_; - theta.subvec(idx_start, idx_start + n_x_ - 1) = vectorise(fit_.x0()); - idx_start += n_x_; - theta.subvec(idx_start, idx_start + n_x_ * n_x_ - 1) = vectorise(fit_.P0()); - idx_start += n_x_ * n_x_; - theta.subvec(idx_start, idx_start + n_y_ * n_x_ - 1) = vectorise(fit_.C()); - idx_start += n_y_ * n_x_; - theta.subvec(idx_start, idx_start + n_y_ - 1) = vectorise(fit_.d()); - idx_start += n_y_; - if (fit_.R().n_elem > 0) { - theta.subvec(idx_start, idx_start + n_y_ * n_y_ - 1) = vectorise(fit_.R()); - } - - return theta; -} - -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_fit_em.h +summary: subspace identification + +--- + +# ldsCtrlEst_h/lds_fit_em.h + +subspace identification [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::EM](/lds-ctrl-est/docs/api/classes/classlds_1_1_e_m/)** | + +## Detailed Description + + + +This file declares the type for fitting a linear dynamical system by expectation-maximization ([lds::EM](/lds-ctrl-est/docs/api/classes/classlds_1_1_e_m/)). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_fit_em.h - EM Fit ----------------------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_EMAX_H +#define LDSCTRLEST_LDS_EMAX_H + +#include "lds_fit.h" + +namespace lds { + +template +class EM { + static_assert(std::is_base_of::value, + "Fit must be derived from lds::Fit type."); + + public: + EM() = default; + + EM(size_t n_x, data_t dt, UniformMatrixList&& u_train, + UniformMatrixList&& z_train); + + EM(const Fit& fit0, UniformMatrixList&& u_train, + UniformMatrixList&& z_train); + + virtual ~EM() = default; + + const Fit& Run(bool calc_dynamics = true, bool calc_Q = true, + bool calc_init = true, bool calc_output = true, + bool calc_measurement = true, size_t max_iter = 100, + data_t tol = 1e-2); + + std::tuple, UniformMatrixList> + ReturnData() { + auto tuple = std::make_tuple(std::move(u_), std::move(z_)); + // auto tuple = std::make_tuple(u_, z_); + u_ = UniformMatrixList(); + z_ = UniformMatrixList(); + return tuple; + } + + const std::vector& x() const { return x_; }; + const std::vector& y() const { return y_; }; + + const Matrix& sum_E_x_t_x_t() const { return sum_E_x_t_x_t_; }; + const Matrix& sum_E_xu_tm1_xu_tm1() const { return sum_E_xu_tm1_xu_tm1_; }; + const Matrix& sum_E_xu_t_xu_tm1() const { return sum_E_xu_t_xu_tm1_; }; + size_t n_t_tot() { return n_t_tot_; } + + const Vector& theta() const { return theta_; }; + + protected: + void Expectation(bool force_common_initial = false); + + void Maximization(bool calc_dynamics = true, bool calc_Q = true, + bool calc_init = false, bool calc_output = false, + bool calc_measurement = false); + + void MaximizeDynamics(); + void MaximizeQ(); + void MaximizeInitial(); + virtual void MaximizeOutput() = 0; + virtual void MaximizeMeasurement() = 0; + + void Smooth(bool force_common_initial); + + virtual void RecurseKe(Matrix& Ke, Cube& P_pre, Cube& P_post, size_t t) = 0; + + void Reset(); + + void InitVars(); + + Vector UpdateTheta(); + + // input/output training data + UniformMatrixList u_; + UniformMatrixList z_; + std::vector x_; + std::vector P_; + std::vector P_t_tm1_; + std::vector y_; + Matrix diag_y_; + + // expectations calculated in E-step + Matrix sum_E_x_t_x_t_; + Matrix sum_E_xu_tm1_xu_tm1_; + Matrix sum_E_xu_t_xu_tm1_; + + Fit fit_; + Vector theta_; + + data_t dt_{}; + size_t n_u_{}; + size_t n_x_{}; + size_t n_y_{}; + size_t n_trials_{}; + std::vector n_t_; + size_t n_t_tot_{}; +}; + +template +EM::EM(size_t n_x, data_t dt, UniformMatrixList&& u_train, + UniformMatrixList&& z_train) { + n_u_ = u_train.at(0).n_rows; + n_y_ = z_train.at(0).n_rows; + fit_ = Fit(n_u_, n_x, n_y_, dt); + u_ = std::move(u_train); + z_ = std::move(z_train); + InitVars(); +} + +template +EM::EM(const Fit& fit0, UniformMatrixList&& u_train, + UniformMatrixList&& z_train) { + // make sure fit dims match I/O data + if (fit0.n_u() != u_train.at(0).n_rows) { + throw std::runtime_error( + "Initial fit and input training data have inconsistent dimensions"); + } + if (fit0.n_y() != z_train.at(0).n_rows) { + throw std::runtime_error( + "Initial fit and output training data have inconsistent dimensions"); + } + + fit_ = fit0; + u_ = std::move(u_train); + z_ = std::move(z_train); + + InitVars(); +} + +template +void EM::InitVars() { + // check input/output data dimensions are consistent + if (z_.size() != u_.size()) { + throw std::runtime_error( + "I/O training data have different number of trials."); + } + n_trials_ = u_.size(); + + n_t_tot_ = 0; + n_t_ = std::vector(n_trials_); + for (size_t trial = 0; trial < n_trials_; trial++) { + if (z_.at(trial).n_cols != u_.at(trial).n_cols) { + throw std::runtime_error( + "I/O training data have different number of time steps."); + } + n_t_[trial] = u_.at(trial).n_cols; + n_t_tot_ += n_t_[trial]; + } + + n_u_ = fit_.n_u(); + n_x_ = fit_.n_x(); + n_y_ = fit_.n_y(); + dt_ = fit_.dt(); + + x_ = std::vector(n_trials_); + P_ = std::vector(n_trials_); + P_t_tm1_ = std::vector(n_trials_); + y_ = std::vector(n_trials_); + for (size_t trial = 0; trial < n_trials_; trial++) { + x_[trial] = Matrix(n_x_, n_t_[trial], fill::zeros); + P_[trial] = Cube(n_x_, n_x_, n_t_[trial], fill::zeros); + P_t_tm1_[trial] = Cube(n_x_, n_x_, n_t_[trial], fill::zeros); + y_[trial] = Matrix(n_y_, n_t_[trial], fill::zeros); + } + + diag_y_ = Matrix(n_y_, n_y_, fill::zeros); + + // covariances in expectation step + sum_E_x_t_x_t_ = Matrix(n_x_, n_x_, fill::zeros); + sum_E_xu_tm1_xu_tm1_ = Matrix(n_x_ + n_u_, n_x_ + n_u_, fill::zeros); + sum_E_xu_t_xu_tm1_ = Matrix(n_x_ + n_u_, n_x_ + n_u_, fill::zeros); +} + +template +const Fit& EM::Run(bool calc_dynamics, bool calc_Q, bool calc_init, + bool calc_output, bool calc_measurement, + size_t max_iter, data_t tol) { + Reset(); // to initial conditions + + size_t n_params = + 3 * n_x_ * n_x_ + n_x_ * n_u_ + n_x_ + n_y_ * n_x_ + n_y_ * n_y_; + Vector theta(n_params); + Vector theta_new(n_params); + data_t max_dtheta = 1; + + // if solving for initial conditions, allow them be varied. + // otherwise, freeze at provided values. + bool force_common_initial = !calc_init; + + // go until parameter convergence + for (size_t l = 0; l < max_iter; l++) { + theta_ = UpdateTheta(); + + std::cout << "Iteration " << l + 1 << "/" << max_iter << " ...\n"; + + Expectation(force_common_initial); + Maximization(calc_dynamics, calc_Q, calc_init, calc_output, + calc_measurement); + + // check convergence + theta_new = UpdateTheta(); + + Vector dtheta = abs(theta_new - theta_) / abs(theta_); + // some parameters could be zero... + arma::uvec ubi_finite = find_finite(dtheta); + + max_dtheta = max(dtheta.elem(ubi_finite)); + std::cout << "max dtheta: " << max_dtheta << "\n"; + if (max_dtheta < tol) { + std::cout << "Converged.\n"; + break; + } + + std::cout << "\n"; + } + + return fit_; +} + +template +void EM::Smooth(bool force_common_initial) { + Matrix k_e(n_x_, n_y_); // estimator gain + Cube k_backfilt; // back-filtering gains + + // TODO(mfbolus): this loop could be made parallel + for (size_t trial = 0; trial < z_.size(); trial++) { + Matrix x_pre(n_x_, n_t_[trial], fill::zeros); + Cube p_pre(n_x_, n_x_, n_t_[trial], fill::zeros); + Matrix x_post(n_x_, n_t_[trial], fill::zeros); + Cube p_post(n_x_, n_x_, n_t_[trial], fill::zeros); + + if (force_common_initial) // forces all trials to have same initial + // conditions. + { + x_[trial].col(0) = fit_.x0(); + P_[trial].slice(0) = fit_.P0(); + } + y_[trial].col(0) = fit_.C() * x_[trial].col(0) + fit_.d(); + + // This *should not* be necessary but make sure P is symmetric. + ForceSymPD(P_[trial].slice(0)); + + x_pre.col(0) = x_[trial].col(0); + p_pre.slice(0) = P_[trial].slice(0); + + x_post.col(0) = x_[trial].col(0); + p_post.slice(0) = P_[trial].slice(0); + + // filter + for (size_t t = 1; t < n_t_[trial]; t++) { + // predict + fit_.f(x_pre, x_post, u_.at(trial), t); + fit_.h(y_[trial], x_pre, t); + diag_y_.diag() = y_[trial].col(t); // TODO(mfbolus): change if parallel + + // update --> posterior estimation + RecurseKe(k_e, p_pre, p_post, t); + x_post.col(t) = + x_pre.col(t) + k_e * (z_.at(trial).col(t) - y_[trial].col(t)); + y_[trial].col(t) = fit_.C() * x_post.col(t) + fit_.d(); + } + + // backfilter -> Smoothed estimate + // Reference: + // Shumway et Stoffer (1982) + ForceSymPD(p_post.slice(n_t_[trial] - 1)); + k_backfilt = Cube(n_x_, n_x_, n_t_[trial], fill::zeros); + x_[trial].col(n_t_[trial] - 1) = x_post.col(n_t_[trial] - 1); + P_[trial].slice(n_t_[trial] - 1) = p_post.slice(n_t_[trial] - 1); + for (size_t t = (n_t_[trial] - 1); t > 0; t--) { + // TODO(mfmbolus): should not be necessary to force symm positive def + ForceSymPD(p_pre.slice(t)); + ForceSymPD(p_post.slice(t - 1)); + ForceSymPD(P_[trial].slice(t)); + k_backfilt.slice(t - 1) = + p_post.slice(t - 1) * fit_.A().t() * inv_sympd(p_pre.slice(t)); + x_[trial].col(t - 1) = + x_post.col(t - 1) + + k_backfilt.slice(t - 1) * (x_[trial].col(t) - x_pre.col(t)); + P_[trial].slice(t - 1) = + p_post.slice(t - 1) + k_backfilt.slice(t - 1) * + (P_[trial].slice(t) - p_pre.slice(t)) * + k_backfilt.slice(t - 1).t(); + } + + // do the same for P_t_tm1 + Matrix id(n_x_, n_x_, fill::eye); + P_t_tm1_[trial].slice(n_t_[trial] - 1) = + (id - k_e * fit_.C()) * fit_.A() * p_post.slice(n_t_[trial] - 2); + for (size_t t = (n_t_[trial] - 1); t > 1; t--) { + P_t_tm1_[trial].slice(t - 1) = + p_post.slice(t - 1) * k_backfilt.slice(t - 2).t() + + k_backfilt.slice(t - 1) * + (P_t_tm1_[trial].slice(t) - fit_.A() * p_post.slice(t - 1)) * + k_backfilt.slice(t - 2).t(); + } + + // finally, get smoothed estimate of output + for (size_t t = 0; t < n_t_[trial]; t++) { + fit_.h(y_[trial], x_[trial], t); + } // samps loop + } // trial loop +} // Smooth + +// template +// void EM::RecurseKe(Matrix& Ke, Cube& P_pre, Cube& P_post, size_t t) { +// // predict covar +// P_pre.slice(t) = fit_.A() * P_post.slice(t - 1) * fit_.A().t() + fit_.Q(); + +// // update Ke +// Ke = P_pre.slice(t) * fit_.C().t() * +// inv_sympd(fit_.C() * P_pre.slice(t) * fit_.C().t() + fit_.R()); + +// // update cov +// // Reference: Ghahramani et Hinton (1996) +// P_post.slice(t) = P_pre.slice(t) - Ke * fit_.C() * P_pre.slice(t); + +// // // n.b. for poisson : +// // P_pre.slice(t) = fit_.A() * P_post.slice(t - 1) * fit_.A().t() + +// fit_.Q(); +// // // update cov +// // P_post.slice(t) = pinv(pinv(P_pre.slice(t)) + fit_.C().t() * diag_y_ * +// // fit_.C()); +// // // update Ke +// // Ke = P_post.slice(t) * fit_.C(); +// } + +template +void EM::Expectation(bool force_common_initial) { + // calculate the mean/cov of state needed for maximizing E[pr(z|theta)] + Smooth(force_common_initial); + + // now get the various forms of sum(E[xx']) needed + // n.b. Going to start at t=1 rather than 0 bc most max terms need that. + // so really "n_t_tot_" is (n_t_tot_-1) + n_t_tot_ = 0; + sum_E_x_t_x_t_ = Matrix(n_x_, n_x_, fill::zeros); + sum_E_xu_tm1_xu_tm1_ = Matrix(n_x_ + n_u_, n_x_ + n_u_, fill::zeros); + sum_E_xu_t_xu_tm1_ = Matrix(n_x_ + n_u_, n_x_ + n_u_, fill::zeros); + + Vector xu_tm1(n_x_ + n_u_, fill::zeros); + Vector xu_t(n_x_ + n_u_, fill::zeros); + + for (size_t trial = 0; trial < z_.size(); trial++) { + for (size_t t = 1; t < n_t_[trial]; t++) { + // ------------ sum_E_x_t_x_t ------------ + sum_E_x_t_x_t_ += x_[trial].col(t) * x_[trial].col(t).t(); + sum_E_x_t_x_t_ += P_[trial].slice(t); + + // ------------ sum_E_xu_tm1_xu_tm1 ------------ + xu_tm1 = join_vert(x_[trial].col(t - 1), u_.at(trial).col(t - 1)); + sum_E_xu_tm1_xu_tm1_ += xu_tm1 * xu_tm1.t(); + sum_E_xu_tm1_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ - 1) += + P_[trial].slice(t - 1); + + // ------------ sum_E_xu_t_xu_tm1 ------------ + xu_t = join_vert(x_[trial].col(t), u_.at(trial).col(t)); + sum_E_xu_t_xu_tm1_ += xu_t * xu_tm1.t(); + sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ - 1) += + P_t_tm1_[trial].slice(t); + + n_t_tot_ += 1; + } // time + } // trial +} // Expectation + +template +void EM::Maximization(bool calc_dynamics, bool calc_Q, bool calc_init, + bool calc_output, bool calc_measurement) { + if (calc_output) { + MaximizeOutput(); + } + + if (calc_measurement) { + MaximizeMeasurement(); + } + + if (calc_dynamics) { + MaximizeDynamics(); + } + + if (calc_Q) { + MaximizeQ(); + } + + if (calc_init) { + MaximizeInitial(); + } +} // Maximization + +template +void EM::MaximizeDynamics() { + // Shumway, Stoffer (1982); Ghahgramani, Hinton (1996) + Matrix ab = sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ + n_u_ - 1) * + inv_sympd(sum_E_xu_tm1_xu_tm1_); + fit_.set_A(ab.submat(0, 0, n_x_ - 1, n_x_ - 1)); + fit_.set_B(ab.submat(0, n_x_, n_x_ - 1, n_x_ + n_u_ - 1)); + std::cout << "A_new[0]: " << fit_.A()[0] << "\n"; + std::cout << "B_new[0]: " << fit_.B()[0] << "\n"; +} + +template +void EM::MaximizeQ() { + // // Shumway, Stoffer (1982); Ghahgramani, Hinton (1996) + // View sum_e_x_t_xu_tm1 = + // sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ + n_u_ - 1); + // Matrix q = sum_E_x_t_x_t_ - sum_e_x_t_xu_tm1 * + // inv_sympd(sum_E_xu_tm1_xu_tm1_) * + // sum_e_x_t_xu_tm1.t(); + // q /= n_t_tot_; + + // this way is same as above iff dynamics were just updated: + // View sum_e_x_t_xu_tm1 = + // sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ + n_u_ - 1); + // Matrix ab = arma::join_horiz(fit_.A(), fit_.B()); + // Matrix q = sum_E_x_t_x_t_ - ab * sum_e_x_t_xu_tm1.t(); + // q /= n_t_tot_; + + // From scratch method: + // Q is covariance of the error between state and dynamics-predicted state + // (aka process noise) + // Q* = E[(x_t - Ax_{t-1} - Bu_{t-1})*(x_t - Ax_{t-1} - Bu_{t-1})'] + // t-1 terms: + View sum_e_x_tm1_x_tm1 = + sum_E_xu_tm1_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ - 1); + View sum_e_u_tm1_u_tm1 = + sum_E_xu_tm1_xu_tm1_.submat(n_x_, n_x_, n_x_ + n_u_ - 1, n_x_ + n_u_ - 1); + View sum_e_x_tm1_u_tm1 = + sum_E_xu_tm1_xu_tm1_.submat(0, n_x_, n_x_ - 1, n_x_ + n_u_ - 1); + + // t, t-1 terms: + View sum_e_x_t_x_tm1 = sum_E_xu_t_xu_tm1_.submat(0, 0, n_x_ - 1, n_x_ - 1); + View sum_e_x_t_u_tm1 = + sum_E_xu_t_xu_tm1_.submat(0, n_x_, n_x_ - 1, n_x_ + n_u_ - 1); + + Matrix q = sum_E_x_t_x_t_; + q += fit_.A() * sum_e_x_tm1_x_tm1 * fit_.A().t(); + q -= sum_e_x_t_x_tm1 * fit_.A().t(); + q -= fit_.A() * sum_e_x_t_x_tm1.t(); + // input-related terms: + q += fit_.B() * sum_e_u_tm1_u_tm1 * fit_.B().t(); + q -= sum_e_x_t_u_tm1 * fit_.B().t(); + q -= fit_.B() * sum_e_x_t_u_tm1.t(); + q += fit_.A() * sum_e_x_tm1_u_tm1 * fit_.B().t(); + q += fit_.B() * sum_e_x_tm1_u_tm1.t() * fit_.A().t(); + q /= n_t_tot_; + + fit_.set_Q(q); + std::cout << "Q_new[0]: " << fit_.Q()[0] << "\n"; + // std::cout << "Q_new: \n" << fit_.Q() << "\n"; +} + +template +void EM::MaximizeInitial() { + Vector x0 = fit_.x0(); + x0.zeros(); + for (size_t trial = 0; trial < z_.size(); trial++) { + x0 += x_[trial].col(0); + } + x0 /= z_.size(); + std::cout << "x0_new[0]: " << x0[0] << "\n"; + + // always recalc P0 even if the initial state is fixed (at zero, for + // example) + Matrix e_var(n_x_, n_x_, fill::zeros); + for (size_t trial = 0; trial < z_.size(); trial++) { + e_var += (x_[trial].col(0) - x0) * (x_[trial].col(0) - x0).t(); + } + e_var /= z_.size(); + + // go ahead and subtract x0*x0' so don't have to below. + e_var -= x0 * x0.t(); + + // To get P0, going to get initial P_ per trial and average. + // (which might be wrong, but need a single number) + Matrix p0 = fit_.P0(); + p0.zeros(); + for (size_t trial = 0; trial < z_.size(); trial++) { + p0 += + (x_[trial].col(0) * x_[trial].col(0).t()) + P_[trial].slice(0) + e_var; + } + p0 /= z_.size(); + + fit_.set_P0(p0); + std::cout << "P0_new[0]: " << fit_.P0()[0] << "\n"; +} + +template +void EM::MaximizeOutput() { + // solve for C+d: + Matrix sum_zx(n_y_, n_x_ + 1, fill::zeros); + Vector x1(n_x_ + 1, fill::zeros); + x1[n_x_] = 1.0; // augment with one to solve for bias + Matrix sum_e_x1_x1(n_x_ + 1, n_x_ + 1, fill::zeros); + for (size_t trial = 0; trial < z_.size(); trial++) { + for (size_t t = 1; t < n_t_[trial]; t++) { + x1.subvec(0, n_x_ - 1) = x_[trial].col(t); + sum_zx += z_.at(trial).col(t) * x1.t(); + sum_e_x1_x1 += x1 * x1.t(); + sum_e_x1_x1.submat(0, 0, n_x_ - 1, n_x_ - 1) += P_[trial].slice(t); + } + } + Matrix cd = sum_zx * inv_sympd(sum_e_x1_x1); + fit_.set_C(cd.submat(0, 0, n_y_ - 1, n_x_ - 1)); + fit_.set_d(vectorise(cd.submat(0, n_x_, n_y_ - 1, n_x_))); + std::cout << "C_new[0]: " << fit_.C()[0] << "\n"; + std::cout << "d_new[0]: " << fit_.d()[0] << "\n"; +} + +template +void EM::MaximizeMeasurement() { + // Solve for measurement noise covar + size_t n_t_tot = 0; + // Ghahgramani, Hinton 1996: + Matrix sum_zz(n_y_, n_y_, fill::zeros); + Matrix sum_yz(n_y_, n_y_, fill::zeros); + for (size_t trial = 0; trial < z_.size(); trial++) { + for (size_t t = 1; t < n_t_[trial]; t++) { + sum_zz += z_.at(trial).col(t) * z_.at(trial).col(t).t(); + // Use Cnew: + sum_yz += + (fit_.C() * x_[trial].col(t) + fit_.d()) * z_.at(trial).col(t).t(); + n_t_tot += 1; + } + } + fit_.set_R((sum_zz - sum_yz) / n_t_tot); + std::cout << "R_new[0]: " << fit_.R()[0] << "\n"; +} + +template +void EM::Reset() { + // reset to initial conditions + for (size_t trial = 0; trial < n_trials_; trial++) { + x_[trial].col(0) = fit_.x0(); + P_[trial].slice(0) = fit_.P0(); + y_[trial].col(0) = fit_.C() * x_[trial].col(0) + fit_.d(); + } +} + +template +Vector EM::UpdateTheta() { + // TODO(mfbolus): This should include n_y_ more params for d. + size_t n_params = 3 * n_x_ * n_x_ + n_x_ * n_u_ + n_x_ + n_y_ * n_x_ + n_y_; + if (fit_.R().n_elem > 0) { + n_params += n_y_ * n_y_; + } + Vector theta(n_params); + + size_t idx_start = 0; + theta.subvec(idx_start, idx_start + n_x_ * n_x_ - 1) = vectorise(fit_.A()); + idx_start += n_x_ * n_x_; + theta.subvec(idx_start, idx_start + n_x_ * n_u_ - 1) = vectorise(fit_.B()); + idx_start += n_x_ * n_u_; + theta.subvec(idx_start, idx_start + n_x_ * n_x_ - 1) = vectorise(fit_.Q()); + idx_start += n_x_ * n_x_; + theta.subvec(idx_start, idx_start + n_x_ - 1) = vectorise(fit_.x0()); + idx_start += n_x_; + theta.subvec(idx_start, idx_start + n_x_ * n_x_ - 1) = vectorise(fit_.P0()); + idx_start += n_x_ * n_x_; + theta.subvec(idx_start, idx_start + n_y_ * n_x_ - 1) = vectorise(fit_.C()); + idx_start += n_y_ * n_x_; + theta.subvec(idx_start, idx_start + n_y_ - 1) = vectorise(fit_.d()); + idx_start += n_y_; + if (fit_.R().n_elem > 0) { + theta.subvec(idx_start, idx_start + n_y_ * n_y_ - 1) = vectorise(fit_.R()); + } + + return theta; +} + +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__fit__ssid_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__fit__ssid_8h.md index c0fd6b5d..a01f7c26 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__fit__ssid_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__fit__ssid_8h.md @@ -1,581 +1,581 @@ ---- -title: ldsCtrlEst_h/lds_fit_ssid.h -summary: subspace identification - ---- - -# ldsCtrlEst_h/lds_fit_ssid.h - -subspace identification [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1ssid/)** | - -## Detailed Description - - - -This file declares and partially defines a template type by which LDS models are fit by a subspace identification (SSID) algorithm (`[lds::SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1ssid/)`). - -References: [1] van Overschee P, de Moore B. (1996) Subspace Identification for Linear Systems. Boston: Springer. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_fit_ssid.h - SSID Fit ------------------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_FIT_SSID_H -#define LDSCTRLEST_LDS_FIT_SSID_H - -#include "lds_fit.h" - -namespace lds { - -template -class SSID { - static_assert(std::is_base_of::value, - "Fit must be derived from lds::Fit type."); - - public: - SSID() = default; - - SSID(size_t n_x, size_t n_h, data_t dt, - UniformMatrixList&& u_train, - UniformMatrixList&& z_train, - const Vector& d = Vector(1).fill(-kInf)); - - std::tuple Run(SSIDWt ssid_wt); - - std::tuple, UniformMatrixList> - ReturnData() { - auto tuple = std::make_tuple(std::move(u_), std::move(z_)); - u_ = UniformMatrixList(); - z_ = UniformMatrixList(); - return tuple; - } - - protected: - void CalcD(data_t t_silence = 0.1, data_t thresh_silence = 0.001); - - void CreateHankelDataMat(); - - virtual void DecomposeData() = 0; - - void CalcSVD(SSIDWt wt); - - void Solve(data_t wt_dc); - - void RecomputeExtObs(); - - // input/output training data - UniformMatrixList u_; - UniformMatrixList z_; - Matrix D_; - - Fit fit_; - Matrix g_dc_; - - data_t dt_{}; - size_t n_u_{}; - size_t n_x_{}; - size_t n_y_{}; - size_t n_h_{}; - size_t n_trials_{}; - std::vector n_t_; - size_t n_t_tot_{}; - - Matrix L_; - Vector s_; - Matrix ext_obs_t_; -}; - -template -SSID::SSID(size_t n_x, size_t n_h, data_t dt, - UniformMatrixList&& u_train, - UniformMatrixList&& z_train, const Vector& d) { - // check input/output data dimensions are consistent - if (z_train.size() != u_train.size()) { - throw std::runtime_error( - "I/O training data have different number of trials."); - } - n_trials_ = u_train.size(); - - n_t_tot_ = 0; - n_t_ = std::vector(n_trials_); - for (size_t trial = 0; trial < n_trials_; trial++) { - if (z_train.at(trial).n_cols != u_train.at(trial).n_cols) { - throw std::runtime_error( - "I/O training data have different number of time steps."); - } - n_t_[trial] = u_train.at(trial).n_cols; - n_t_tot_ += n_t_[trial]; - } - - dt_ = dt; - n_x_ = n_x; - n_u_ = u_train.at(0).n_rows; - n_y_ = z_train.at(0).n_rows; - n_h_ = n_h; - - // dimensionality check for eventual block-hankel data matrix - size_t len = n_t_tot_ - 2 * n_h_ + 1; - if (len < (2 * n_h_ * (n_u_ + n_y_))) { - std::ostringstream ss; - ss << "Dataset problem! More rows than columns in block-hankel data " - "matrix: 2*(n_u+n_y)*n_h > data-length! Need higher data-length or " - "lower n_h."; - throw std::runtime_error(ss.str()); - } - - fit_ = Fit(n_u_, n_x_, n_y_, dt_); - - u_ = std::move(u_train); - z_ = std::move(z_train); - - if (!d.is_finite() || (d.n_rows != n_y_)) { - // TODO(mfbolus): implement least-square solution for impulse response with - // a second input of ones. Data-driven way of accounting for offset *not* - // driven by an input. - // - // For now, calculate output bias (d) as the - // output wherever the stimulus has not been on for some amount of time. - // convolve u with rectangle and take all samples. This is a reasonable - // approach, since often when autonomous systems are fit (i.e., systems with - // no input), they will subtract off the mean of the output. This - // essentially amounts to setting output bias to the mean of the output when - // there is no stimulation. - data_t t_silence = 0.1; - data_t thresh_silence = 0.001; - CalcD(t_silence, thresh_silence); - } else { - fit_.set_d(d); - } -} - -template -std::tuple SSID::Run(SSIDWt ssid_wt) { - // the weight on minimizing dc I/O gain only works for gaussian, - // and hopefully not necessary with appropriate dataset. - data_t wt_dc = 0; - // std::cout << "creating hankel mat\n"; - CreateHankelDataMat(); - // std::cout << "decomposing data\n"; - DecomposeData(); - // std::cout << "calculating svd\n"; - CalcSVD(ssid_wt); - // std::cout << "solving for params\n"; - Solve(wt_dc); - // std::cout << "fin\n"; - return std::make_tuple(fit_, s_); -} - -template -void SSID::CalcD(data_t t_silence, data_t thresh_silence) { - Vector d(z_.at(0).n_rows, fill::zeros); - Vector win(static_cast(t_silence / dt_), fill::ones); - Vector sum_z_silence(n_y_, fill::zeros); - size_t n_silence(0); - for (size_t trial = 0; trial < u_.size(); trial++) { - // find silent samples - // start by convolving with - Vector sum_u = vectorise(sum(abs(u_.at(trial)), 0)); - Vector u_conv = conv(sum_u, win, "same"); - - // get only the samples that are silent... - arma::uvec ubi_silence = find(u_conv <= thresh_silence); - if (ubi_silence.n_elem > 0) { - sum_z_silence += arma::sum(z_.at(trial).cols(ubi_silence), 1); - n_silence += ubi_silence.n_elem; - } - } - if (n_silence > 0) { - d = sum_z_silence / n_silence; - } - fit_.set_d(d); -} - -template -void SSID::CreateHankelDataMat() { - // temporary copy of data - Matrix z(n_y_, n_t_tot_, fill::zeros); - Matrix u(n_u_, n_t_tot_, fill::zeros); - size_t so_far(0); - - for (size_t trial = 0; trial < z_.size(); trial++) { - z.submat(0, so_far, n_y_ - 1, so_far + n_t_.at(trial) - 1) = z_.at(trial); - u.submat(0, so_far, n_u_ - 1, so_far + n_t_.at(trial) - 1) = u_.at(trial); - so_far += n_t_.at(trial); - } - - // remove output bias - z.each_col() -= fit_.d(); - - // calculate I/O gain @ DC while data in convenient form - g_dc_ = z * pinv(u); - // std::cout << "G0_data = " << g_dc_ << "\n"; - - // create hankel data matrix - size_t len = z.n_cols - 2 * n_h_ + 1; // data length in hankel mat - - // block-hankel data matrix - D_ = Matrix(2 * n_h_ * (n_u_ + n_y_), len, fill::zeros); - // past input - auto u_p = D_.submat(0, 0, n_h_ * n_u_ - 1, len - 1); - // future input - auto u_f = D_.submat(n_h_ * n_u_, 0, 2 * n_h_ * n_u_ - 1, len - 1); - // past output - auto y_p = - D_.submat(2 * n_h_ * n_u_, 0, n_h_ * (2 * n_u_ + n_y_) - 1, len - 1); - // future output - auto y_f = D_.submat(n_h_ * (2 * n_u_ + n_y_), 0, - 2 * n_h_ * (n_u_ + n_y_) - 1, len - 1); - - size_t idx = 0; - for (size_t k = 0; k < len; k++) { - idx = 0; - for (size_t kk = k; kk < (n_h_ + k); kk++) { - u_p.col(k).subvec(idx, idx + n_u_ - 1) = u.col(kk); - idx += n_u_; - } - - idx = 0; - for (size_t kk = (n_h_ + k); kk < (2 * n_h_ + k); kk++) { - u_f.col(k).subvec(idx, idx + n_u_ - 1) = u.col(kk); - idx += n_u_; - } - - idx = 0; - for (size_t kk = k; kk < (n_h_ + k); kk++) { - y_p.col(k).subvec(idx, idx + n_y_ - 1) = z.col(kk); - idx += n_y_; - } - - idx = 0; - for (size_t kk = (n_h_ + k); kk < (2 * n_h_ + k); kk++) { - y_f.col(k).subvec(idx, idx + n_y_ - 1) = z.col(kk); - idx += n_y_; - } - } - - D_ /= sqrt(static_cast(len)); -} - -// template -// void SSID::DecomposeData() { -// // do LQ decomp instead of calculating covariance expensive way -// // Note that "R" in van Overschee is lower-triangular (L), not "R" in QR -// // decomp. Very confusing. -// Matrix q_t; -// lq(L_, q_t, D_); -// // van Overschee zeros out the other elements. -// L_ = trimatl(L_); -// } - -template -void SSID::CalcSVD(SSIDWt wt) { - // submats that will be needed: - auto R_14_14 = L_.submat(0, 0, n_h_ * (2 * n_u_ + n_y_) - 1, - n_h_ * (2 * n_u_ + n_y_) - 1); - auto R_11_14 = L_.submat(0, 0, n_h_ * n_u_ - 1, n_h_ * (2 * n_u_ + n_y_) - 1); - auto R_11_13 = L_.submat(0, 0, n_h_ * n_u_ - 1, n_h_ * (2 * n_u_) - 1); - auto R_23_13 = - L_.submat(n_h_ * n_u_, 0, 2 * n_h_ * n_u_ - 1, 2 * n_h_ * n_u_ - 1); - auto R_44_14 = L_.submat(2 * n_u_ * n_h_, 0, n_h_ * (2 * n_u_ + n_y_) - 1, - n_h_ * (2 * n_u_ + n_y_) - 1); - auto R_44_13 = L_.submat(2 * n_u_ * n_h_, 0, n_h_ * (2 * n_u_ + n_y_) - 1, - n_h_ * (2 * n_u_) - 1); - auto R_44 = - L_.submat(2 * n_u_ * n_h_, 2 * n_u_ * n_h_, n_h_ * (2 * n_u_ + n_y_) - 1, - n_h_ * (2 * n_u_ + n_y_) - 1); - auto R_56_14 = - L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, n_h_ * (2 * n_u_ + 2 * n_y_) - 1, - n_h_ * (2 * n_u_ + n_y_) - 1); - - Matrix Lup_Luf_Lyp = R_56_14 * pinv(R_14_14); - auto Lup = Lup_Luf_Lyp.submat(0, 0, n_h_ * n_y_ - 1, n_h_ * n_u_ - 1); - auto Luf = - Lup_Luf_Lyp.submat(0, n_h_ * n_u_, n_h_ * n_y_ - 1, 2 * n_h_ * n_u_ - 1); - auto Lyp = Lup_Luf_Lyp.submat(0, 2 * n_h_ * n_u_, n_h_ * n_y_ - 1, - n_h_ * (2 * n_u_ + n_y_) - 1); - - // aka: R_f - Matrix R_56_16 = L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, - 2 * n_h_ * (n_u_ + n_y_) - 1, L_.n_cols - 1); - // from van Overschee subid.m: - // Rf = R((2*m+l)*i+1:2*(m+l)*i,:); % Future outputs - - Matrix U; - Matrix V; - switch (wt) { - case kSSIDNone: { - // No weighting. (what van Overschee calls "N4SID") - Matrix O_k_sans_Qt = Lup * R_11_14 + Lyp * R_44_14; - arma::svd(U, s_, V, O_k_sans_Qt, "std"); - } break; - case kSSIDMOESP: { - // MOESP weighting - // This is what they use in the "robust" algorithm van Overschee, de Moor - // 1996 - Matrix Pi = Matrix(2 * n_h_ * n_u_, 2 * n_h_ * n_u_, fill::eye) - - R_23_13.t() * inv(R_23_13 * R_23_13.t()) * R_23_13; - Matrix O_k_ortho_Uf_sans_Qt = - join_horiz((Lup * R_11_13 + Lyp * R_44_13) * Pi, Lyp * R_44); - svd(U, s_, V, O_k_ortho_Uf_sans_Qt, "std"); - } break; - case kSSIDCVA: { - // CVA weighting - // See van Overschee's matlab code (subid.m): - // https://www.mathworks.com/matlabcentral/fileexchange/2290-subspace-identification-for-linear-systems - Matrix Pi = Matrix(2 * n_h_ * n_u_, 2 * n_h_ * n_u_, fill::eye) - - R_23_13.t() * inv(R_23_13 * R_23_13.t()) * R_23_13; - Matrix O_k_ortho_Uf_sans_Qt = - join_horiz((Lup * R_11_13 + Lyp * R_44_13) * Pi, Lyp * R_44); - - Matrix inv_w1; - Matrix qt1; - lq(inv_w1, qt1, R_56_16); // lq decomp of R_f (future output data) - inv_w1 = trimatl(inv_w1); - inv_w1 = inv_w1.submat(0, 0, n_y_ * n_h_ - 1, n_y_ * n_h_ - 1); - Matrix w_o_w = arma::solve( - inv_w1, O_k_ortho_Uf_sans_Qt); // alternatively - // pinv(inv_W1)*O_k_ortho_Uf_sans_Qt - svd(U, s_, V, w_o_w, "std"); - - U = inv_w1 * U; - break; - } - } - - // Truncate to model order (heart of ssid method) - auto s_hat = s_.subvec(0, n_x_ - 1); - Matrix diag_sqrt_s = diagmat(sqrt(s_hat)); - auto u_hat = U.submat(0, 0, U.n_rows - 1, n_x_ - 1); - - // get extended observability and controllability mats - ext_obs_t_ = u_hat * diag_sqrt_s; // extended observability matrix -} - -template -void SSID::Solve(data_t wt_dc) { - // required submats - auto R_56_14 = - L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, n_h_ * (2 * n_u_ + 2 * n_y_) - 1, - n_h_ * (2 * n_u_ + n_y_) - 1); - auto R_23_15 = L_.submat(n_h_ * n_u_, 0, 2 * n_h_ * n_u_ - 1, - n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1); - auto R_66_15 = L_.submat(n_h_ * (2 * n_u_ + n_y_) + n_y_, 0, - 2 * n_h_ * (n_u_ + n_y_) - 1, - n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1); - auto R_55_15 = L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, - n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1, - n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1); - auto R_56_15 = - L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, 2 * n_h_ * (n_u_ + n_y_) - 1, - n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1); - - // Solve for params using appropriate algorithm: - // robust deterministic/stochastic algorithm in van Overschee 1996 - // algorithm that the authors say "works" in practice. - auto ext_obs_tm1 = ext_obs_t_.submat( - 0, 0, ext_obs_t_.n_rows - 1 - n_y_, - ext_obs_t_.n_cols - 1); // extended observability matrix - - // This is what textbook (1996) says: - // - // Matrix Tr = join_vert(pinv(ext_obs_t_) * R_56_15, R_23_15); - // - // HOWEVER, do not know why but have to fill the last place with zeros like - // authors' matlab implementation (see `subid.m`) - // Otherwise, get ridiculous covariances (although A,C estimates are close to - // same...) - Matrix Tr = join_vert( - join_horiz(pinv(ext_obs_t_) * R_56_14, Matrix(n_x_, n_y_, fill::zeros)), - R_23_15); - Matrix Tl = join_vert(pinv(ext_obs_tm1) * R_66_15, R_55_15); - Matrix S = Tl * pinv(Tr); - - // Use alternative in van Overschee 1996, p. 129. Apparently, should ensure - // stability. - fit_.set_C(ext_obs_t_.submat(0, 0, n_y_ - 1, ext_obs_t_.n_cols - 1)); - Matrix ext_obs_t_p1 = join_vert( - ext_obs_t_.submat(n_y_, 0, ext_obs_t_.n_rows - 1, ext_obs_t_.n_cols - 1), - Matrix(n_y_, ext_obs_t_.n_cols, fill::zeros)); - fit_.set_A(pinv(ext_obs_t_) * ext_obs_t_p1); - - // At this point, van Overschee & de Moor suggest re-calculating ext_obs_t_, - // ext_obs_tm1 from (A, C) because it was just an approximation. This is - RecomputeExtObs(); - ext_obs_tm1 = ext_obs_t_.submat( - 0, 0, ext_obs_t_.n_rows - 1 - n_y_, - ext_obs_t_.n_cols - 1); // extended observability matrix - Tl = join_vert(pinv(ext_obs_tm1) * R_66_15, R_55_15); - Tr = join_vert( - join_horiz(pinv(ext_obs_t_) * R_56_14, Matrix(n_x_, n_y_, fill::zeros)), - R_23_15); - S = Tl * pinv(Tr); - - Matrix Lcurly = S.submat(0, 0, n_x_ + n_y_ - 1, n_x_ - 1) * pinv(ext_obs_t_); - Matrix Mcurly = pinv(ext_obs_tm1); - Matrix Pcurly = Tl - Lcurly * R_56_15; - Vector Pvec = vectorise(Pcurly); - Matrix Qcurly = R_23_15; - - // Identify [D; B], assuming D=0 and ensuring DC gain is correct - Matrix sum_QcurlyT_kron_Ncurly( - (n_h_ * (2 * n_u_ + n_y_) + n_y_) * (n_y_ + n_x_), n_u_ * (n_y_ + n_x_), - fill::zeros); - - Matrix eye_ext_obs_tm1(n_y_ + ext_obs_tm1.n_rows, n_y_ + ext_obs_tm1.n_cols, - fill::eye); - eye_ext_obs_tm1.submat(n_y_, n_y_, eye_ext_obs_tm1.n_rows - 1, - eye_ext_obs_tm1.n_cols - 1) = ext_obs_tm1; - - // van Overschee (1996) p. 126 - Matrix N1_Tl = -Lcurly; - N1_Tl.submat(0, 0, n_x_ - 1, N1_Tl.n_cols - 1) += - join_horiz(Matrix(n_x_, n_y_, fill::zeros), Mcurly); - N1_Tl.submat(n_x_, 0, n_x_ + n_y_ - 1, n_y_ - 1) += - Matrix(n_y_, n_y_, fill::eye); - - Matrix Nk_Tl(N1_Tl.n_rows, N1_Tl.n_cols, fill::zeros); - Matrix N_k; - for (size_t k = 0; k < n_h_; k++) { - auto Qcurly_k = - Qcurly.submat(n_u_ * k, 0, n_u_ * (k + 1) - 1, Qcurly.n_cols - 1); - - Nk_Tl.zeros(); - Nk_Tl.submat(0, 0, n_x_ + n_y_ - 1, Nk_Tl.n_cols - k * n_y_ - 1) = - N1_Tl.submat(0, k * n_y_, N1_Tl.n_rows - 1, N1_Tl.n_cols - 1); - N_k = Nk_Tl * eye_ext_obs_tm1; - - sum_QcurlyT_kron_Ncurly += kron(Qcurly_k.t(), N_k); - } - - Matrix err_vec; - if (wt_dc > 0) { - // Constraints enforced by weighted least squares - // - // Reference: - // - // Privara S, ..., Ferkl L_. (2010) Subspace Identification of Poorly - // Excited Industrial Systems. Conference in Decision and Control. - - // constraint 1: assume D=0 --> remove the components for Dvec (this is - // actually a hard constraint in that it ignores D) - Matrix sum_QcurlyT_kron_Ncurly_db = sum_QcurlyT_kron_Ncurly; - sum_QcurlyT_kron_Ncurly = - Matrix(sum_QcurlyT_kron_Ncurly_db.n_rows, n_x_ * n_u_); - - size_t kkk = 0; - for (size_t k = 1; k < (n_u_ + 1); k++) { - size_t start_idx = k * (n_y_ + n_x_) - n_x_; - for (size_t kk = 0; kk < n_x_; kk++) { - sum_QcurlyT_kron_Ncurly.col(kkk) = - sum_QcurlyT_kron_Ncurly_db.col(start_idx + kk); - kkk++; - } - } - - // constraint 2: Make sure DC I/O gain is correct - Matrix b_to_g0 = fit_.C() * inv(Matrix(n_x_, n_x_, fill::eye) - fit_.A()); - Matrix Pvec_Gvec = join_vert(Pvec, vectorise(g_dc_)); - Matrix eye_kron_b_to_g0 = kron(Matrix(n_u_, n_u_, fill::eye), b_to_g0); - Matrix sum_QcurlyT_kron_Ncurly_b_to_g0 = - join_vert(sum_QcurlyT_kron_Ncurly, eye_kron_b_to_g0); - - // WEIGHTED LS - // Important in practice because I care a lot about at least getting the DC - // gain correct. Put x weight on minimizing error at DC, relative to others - Matrix w(sum_QcurlyT_kron_Ncurly_b_to_g0.n_rows, - sum_QcurlyT_kron_Ncurly_b_to_g0.n_rows, fill::eye); - // Make weight on minimizing DC error immense so at least that - // should be nailed. - size_t start_row = sum_QcurlyT_kron_Ncurly.n_rows; - size_t start_col = sum_QcurlyT_kron_Ncurly.n_rows; - size_t stop_row = w.n_rows - 1; - size_t stop_col = w.n_cols - 1; - // w.submat(start_row, start_col, stop_row, stop_col) *= wt_dc*N;// scale - // weight with data length? - w.submat(start_row, start_col, stop_row, stop_col) *= wt_dc; - Vector b_vec = inv(sum_QcurlyT_kron_Ncurly_b_to_g0.t() * w * - sum_QcurlyT_kron_Ncurly_b_to_g0) * - sum_QcurlyT_kron_Ncurly_b_to_g0.t() * w * Pvec_Gvec; - - fit_.set_B(Matrix(b_vec.memptr(), n_x_, n_u_)); - - // Calculate residuals and their cov. - // Because I've added constraints, I need to re-calculate the right term - // with b_vec instead of how van Overschee do in final algorithm. - err_vec = Pvec - sum_QcurlyT_kron_Ncurly * b_vec; - } else { - // default way: *no* constraint on G0 or D=0 - Vector db_vec = pinv(sum_QcurlyT_kron_Ncurly) * Pvec; - // TODO(mfbolus) n.b., this gets thrown away... - // Matrix D = Matrix(db_vec.memptr(), n_y_, n_u_); - fit_.set_B(Matrix(db_vec.memptr() + (n_u_ * n_y_), n_x_, n_u_)); - err_vec = Pvec - sum_QcurlyT_kron_Ncurly * db_vec; - } - // Matrix err = Matrix(err_vec.memptr(), Pcurly.n_rows, Pcurly.n_cols); - - // TODO(mfbolus): Something is wrong with the error calculation above. - // Use the way van overschee does it in `subid.m` - // WARNING: this ignores any above constraints, so Q, R will be approximate... - Matrix err = Tl - S * Tr; - Matrix cov_err = err * err.t(); - fit_.set_Q(cov_err.submat(0, 0, n_x_ - 1, n_x_ - 1)); - fit_.set_R(cov_err.submat(n_x_, n_x_, n_x_ + n_y_ - 1, n_x_ + n_y_ - 1)); -} - -template -void SSID::RecomputeExtObs() { - ext_obs_t_.submat(0, 0, n_y_ - 1, ext_obs_t_.n_cols - 1) = fit_.C(); - for (size_t k = 2; k < (n_h_ + 1); k++) { - ext_obs_t_.submat((k - 1) * n_y_, 0, k * n_y_ - 1, ext_obs_t_.n_cols - 1) = - ext_obs_t_.submat((k - 2) * n_y_, 0, (k - 1) * n_y_ - 1, - ext_obs_t_.n_cols - 1) * - fit_.A(); - } -} - -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_fit_ssid.h +summary: subspace identification + +--- + +# ldsCtrlEst_h/lds_fit_ssid.h + +subspace identification [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1_s_s_i_d/)** | + +## Detailed Description + + + +This file declares and partially defines a template type by which LDS models are fit by a subspace identification (SSID) algorithm (`[lds::SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1_s_s_i_d/)`). + +References: [1] van Overschee P, de Moore B. (1996) Subspace Identification for Linear Systems. Boston: Springer. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_fit_ssid.h - SSID Fit ------------------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_FIT_SSID_H +#define LDSCTRLEST_LDS_FIT_SSID_H + +#include "lds_fit.h" + +namespace lds { + +template +class SSID { + static_assert(std::is_base_of::value, + "Fit must be derived from lds::Fit type."); + + public: + SSID() = default; + + SSID(size_t n_x, size_t n_h, data_t dt, + UniformMatrixList&& u_train, + UniformMatrixList&& z_train, + const Vector& d = Vector(1).fill(-kInf)); + + std::tuple Run(SSIDWt ssid_wt); + + std::tuple, UniformMatrixList> + ReturnData() { + auto tuple = std::make_tuple(std::move(u_), std::move(z_)); + u_ = UniformMatrixList(); + z_ = UniformMatrixList(); + return tuple; + } + + protected: + void CalcD(data_t t_silence = 0.1, data_t thresh_silence = 0.001); + + void CreateHankelDataMat(); + + virtual void DecomposeData() = 0; + + void CalcSVD(SSIDWt wt); + + void Solve(data_t wt_dc); + + void RecomputeExtObs(); + + // input/output training data + UniformMatrixList u_; + UniformMatrixList z_; + Matrix D_; + + Fit fit_; + Matrix g_dc_; + + data_t dt_{}; + size_t n_u_{}; + size_t n_x_{}; + size_t n_y_{}; + size_t n_h_{}; + size_t n_trials_{}; + std::vector n_t_; + size_t n_t_tot_{}; + + Matrix L_; + Vector s_; + Matrix ext_obs_t_; +}; + +template +SSID::SSID(size_t n_x, size_t n_h, data_t dt, + UniformMatrixList&& u_train, + UniformMatrixList&& z_train, const Vector& d) { + // check input/output data dimensions are consistent + if (z_train.size() != u_train.size()) { + throw std::runtime_error( + "I/O training data have different number of trials."); + } + n_trials_ = u_train.size(); + + n_t_tot_ = 0; + n_t_ = std::vector(n_trials_); + for (size_t trial = 0; trial < n_trials_; trial++) { + if (z_train.at(trial).n_cols != u_train.at(trial).n_cols) { + throw std::runtime_error( + "I/O training data have different number of time steps."); + } + n_t_[trial] = u_train.at(trial).n_cols; + n_t_tot_ += n_t_[trial]; + } + + dt_ = dt; + n_x_ = n_x; + n_u_ = u_train.at(0).n_rows; + n_y_ = z_train.at(0).n_rows; + n_h_ = n_h; + + // dimensionality check for eventual block-hankel data matrix + size_t len = n_t_tot_ - 2 * n_h_ + 1; + if (len < (2 * n_h_ * (n_u_ + n_y_))) { + std::ostringstream ss; + ss << "Dataset problem! More rows than columns in block-hankel data " + "matrix: 2*(n_u+n_y)*n_h > data-length! Need higher data-length or " + "lower n_h."; + throw std::runtime_error(ss.str()); + } + + fit_ = Fit(n_u_, n_x_, n_y_, dt_); + + u_ = std::move(u_train); + z_ = std::move(z_train); + + if (!d.is_finite() || (d.n_rows != n_y_)) { + // TODO(mfbolus): implement least-square solution for impulse response with + // a second input of ones. Data-driven way of accounting for offset *not* + // driven by an input. + // + // For now, calculate output bias (d) as the + // output wherever the stimulus has not been on for some amount of time. + // convolve u with rectangle and take all samples. This is a reasonable + // approach, since often when autonomous systems are fit (i.e., systems with + // no input), they will subtract off the mean of the output. This + // essentially amounts to setting output bias to the mean of the output when + // there is no stimulation. + data_t t_silence = 0.1; + data_t thresh_silence = 0.001; + CalcD(t_silence, thresh_silence); + } else { + fit_.set_d(d); + } +} + +template +std::tuple SSID::Run(SSIDWt ssid_wt) { + // the weight on minimizing dc I/O gain only works for gaussian, + // and hopefully not necessary with appropriate dataset. + data_t wt_dc = 0; + // std::cout << "creating hankel mat\n"; + CreateHankelDataMat(); + // std::cout << "decomposing data\n"; + DecomposeData(); + // std::cout << "calculating svd\n"; + CalcSVD(ssid_wt); + // std::cout << "solving for params\n"; + Solve(wt_dc); + // std::cout << "fin\n"; + return std::make_tuple(fit_, s_); +} + +template +void SSID::CalcD(data_t t_silence, data_t thresh_silence) { + Vector d(z_.at(0).n_rows, fill::zeros); + Vector win(static_cast(t_silence / dt_), fill::ones); + Vector sum_z_silence(n_y_, fill::zeros); + size_t n_silence(0); + for (size_t trial = 0; trial < u_.size(); trial++) { + // find silent samples + // start by convolving with + Vector sum_u = vectorise(sum(abs(u_.at(trial)), 0)); + Vector u_conv = conv(sum_u, win, "same"); + + // get only the samples that are silent... + arma::uvec ubi_silence = find(u_conv <= thresh_silence); + if (ubi_silence.n_elem > 0) { + sum_z_silence += arma::sum(z_.at(trial).cols(ubi_silence), 1); + n_silence += ubi_silence.n_elem; + } + } + if (n_silence > 0) { + d = sum_z_silence / n_silence; + } + fit_.set_d(d); +} + +template +void SSID::CreateHankelDataMat() { + // temporary copy of data + Matrix z(n_y_, n_t_tot_, fill::zeros); + Matrix u(n_u_, n_t_tot_, fill::zeros); + size_t so_far(0); + + for (size_t trial = 0; trial < z_.size(); trial++) { + z.submat(0, so_far, n_y_ - 1, so_far + n_t_.at(trial) - 1) = z_.at(trial); + u.submat(0, so_far, n_u_ - 1, so_far + n_t_.at(trial) - 1) = u_.at(trial); + so_far += n_t_.at(trial); + } + + // remove output bias + z.each_col() -= fit_.d(); + + // calculate I/O gain @ DC while data in convenient form + g_dc_ = z * pinv(u); + // std::cout << "G0_data = " << g_dc_ << "\n"; + + // create hankel data matrix + size_t len = z.n_cols - 2 * n_h_ + 1; // data length in hankel mat + + // block-hankel data matrix + D_ = Matrix(2 * n_h_ * (n_u_ + n_y_), len, fill::zeros); + // past input + auto u_p = D_.submat(0, 0, n_h_ * n_u_ - 1, len - 1); + // future input + auto u_f = D_.submat(n_h_ * n_u_, 0, 2 * n_h_ * n_u_ - 1, len - 1); + // past output + auto y_p = + D_.submat(2 * n_h_ * n_u_, 0, n_h_ * (2 * n_u_ + n_y_) - 1, len - 1); + // future output + auto y_f = D_.submat(n_h_ * (2 * n_u_ + n_y_), 0, + 2 * n_h_ * (n_u_ + n_y_) - 1, len - 1); + + size_t idx = 0; + for (size_t k = 0; k < len; k++) { + idx = 0; + for (size_t kk = k; kk < (n_h_ + k); kk++) { + u_p.col(k).subvec(idx, idx + n_u_ - 1) = u.col(kk); + idx += n_u_; + } + + idx = 0; + for (size_t kk = (n_h_ + k); kk < (2 * n_h_ + k); kk++) { + u_f.col(k).subvec(idx, idx + n_u_ - 1) = u.col(kk); + idx += n_u_; + } + + idx = 0; + for (size_t kk = k; kk < (n_h_ + k); kk++) { + y_p.col(k).subvec(idx, idx + n_y_ - 1) = z.col(kk); + idx += n_y_; + } + + idx = 0; + for (size_t kk = (n_h_ + k); kk < (2 * n_h_ + k); kk++) { + y_f.col(k).subvec(idx, idx + n_y_ - 1) = z.col(kk); + idx += n_y_; + } + } + + D_ /= sqrt(static_cast(len)); +} + +// template +// void SSID::DecomposeData() { +// // do LQ decomp instead of calculating covariance expensive way +// // Note that "R" in van Overschee is lower-triangular (L), not "R" in QR +// // decomp. Very confusing. +// Matrix q_t; +// lq(L_, q_t, D_); +// // van Overschee zeros out the other elements. +// L_ = trimatl(L_); +// } + +template +void SSID::CalcSVD(SSIDWt wt) { + // submats that will be needed: + auto R_14_14 = L_.submat(0, 0, n_h_ * (2 * n_u_ + n_y_) - 1, + n_h_ * (2 * n_u_ + n_y_) - 1); + auto R_11_14 = L_.submat(0, 0, n_h_ * n_u_ - 1, n_h_ * (2 * n_u_ + n_y_) - 1); + auto R_11_13 = L_.submat(0, 0, n_h_ * n_u_ - 1, n_h_ * (2 * n_u_) - 1); + auto R_23_13 = + L_.submat(n_h_ * n_u_, 0, 2 * n_h_ * n_u_ - 1, 2 * n_h_ * n_u_ - 1); + auto R_44_14 = L_.submat(2 * n_u_ * n_h_, 0, n_h_ * (2 * n_u_ + n_y_) - 1, + n_h_ * (2 * n_u_ + n_y_) - 1); + auto R_44_13 = L_.submat(2 * n_u_ * n_h_, 0, n_h_ * (2 * n_u_ + n_y_) - 1, + n_h_ * (2 * n_u_) - 1); + auto R_44 = + L_.submat(2 * n_u_ * n_h_, 2 * n_u_ * n_h_, n_h_ * (2 * n_u_ + n_y_) - 1, + n_h_ * (2 * n_u_ + n_y_) - 1); + auto R_56_14 = + L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, n_h_ * (2 * n_u_ + 2 * n_y_) - 1, + n_h_ * (2 * n_u_ + n_y_) - 1); + + Matrix Lup_Luf_Lyp = R_56_14 * pinv(R_14_14); + auto Lup = Lup_Luf_Lyp.submat(0, 0, n_h_ * n_y_ - 1, n_h_ * n_u_ - 1); + auto Luf = + Lup_Luf_Lyp.submat(0, n_h_ * n_u_, n_h_ * n_y_ - 1, 2 * n_h_ * n_u_ - 1); + auto Lyp = Lup_Luf_Lyp.submat(0, 2 * n_h_ * n_u_, n_h_ * n_y_ - 1, + n_h_ * (2 * n_u_ + n_y_) - 1); + + // aka: R_f + Matrix R_56_16 = L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, + 2 * n_h_ * (n_u_ + n_y_) - 1, L_.n_cols - 1); + // from van Overschee subid.m: + // Rf = R((2*m+l)*i+1:2*(m+l)*i,:); % Future outputs + + Matrix U; + Matrix V; + switch (wt) { + case kSSIDNone: { + // No weighting. (what van Overschee calls "N4SID") + Matrix O_k_sans_Qt = Lup * R_11_14 + Lyp * R_44_14; + arma::svd(U, s_, V, O_k_sans_Qt, "std"); + } break; + case kSSIDMOESP: { + // MOESP weighting + // This is what they use in the "robust" algorithm van Overschee, de Moor + // 1996 + Matrix Pi = Matrix(2 * n_h_ * n_u_, 2 * n_h_ * n_u_, fill::eye) - + R_23_13.t() * inv(R_23_13 * R_23_13.t()) * R_23_13; + Matrix O_k_ortho_Uf_sans_Qt = + join_horiz((Lup * R_11_13 + Lyp * R_44_13) * Pi, Lyp * R_44); + svd(U, s_, V, O_k_ortho_Uf_sans_Qt, "std"); + } break; + case kSSIDCVA: { + // CVA weighting + // See van Overschee's matlab code (subid.m): + // https://www.mathworks.com/matlabcentral/fileexchange/2290-subspace-identification-for-linear-systems + Matrix Pi = Matrix(2 * n_h_ * n_u_, 2 * n_h_ * n_u_, fill::eye) - + R_23_13.t() * inv(R_23_13 * R_23_13.t()) * R_23_13; + Matrix O_k_ortho_Uf_sans_Qt = + join_horiz((Lup * R_11_13 + Lyp * R_44_13) * Pi, Lyp * R_44); + + Matrix inv_w1; + Matrix qt1; + lq(inv_w1, qt1, R_56_16); // lq decomp of R_f (future output data) + inv_w1 = trimatl(inv_w1); + inv_w1 = inv_w1.submat(0, 0, n_y_ * n_h_ - 1, n_y_ * n_h_ - 1); + Matrix w_o_w = arma::solve( + inv_w1, O_k_ortho_Uf_sans_Qt); // alternatively + // pinv(inv_W1)*O_k_ortho_Uf_sans_Qt + svd(U, s_, V, w_o_w, "std"); + + U = inv_w1 * U; + break; + } + } + + // Truncate to model order (heart of ssid method) + auto s_hat = s_.subvec(0, n_x_ - 1); + Matrix diag_sqrt_s = diagmat(sqrt(s_hat)); + auto u_hat = U.submat(0, 0, U.n_rows - 1, n_x_ - 1); + + // get extended observability and controllability mats + ext_obs_t_ = u_hat * diag_sqrt_s; // extended observability matrix +} + +template +void SSID::Solve(data_t wt_dc) { + // required submats + auto R_56_14 = + L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, n_h_ * (2 * n_u_ + 2 * n_y_) - 1, + n_h_ * (2 * n_u_ + n_y_) - 1); + auto R_23_15 = L_.submat(n_h_ * n_u_, 0, 2 * n_h_ * n_u_ - 1, + n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1); + auto R_66_15 = L_.submat(n_h_ * (2 * n_u_ + n_y_) + n_y_, 0, + 2 * n_h_ * (n_u_ + n_y_) - 1, + n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1); + auto R_55_15 = L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, + n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1, + n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1); + auto R_56_15 = + L_.submat(n_h_ * (2 * n_u_ + n_y_), 0, 2 * n_h_ * (n_u_ + n_y_) - 1, + n_h_ * (2 * n_u_ + n_y_) + n_y_ - 1); + + // Solve for params using appropriate algorithm: + // robust deterministic/stochastic algorithm in van Overschee 1996 + // algorithm that the authors say "works" in practice. + auto ext_obs_tm1 = ext_obs_t_.submat( + 0, 0, ext_obs_t_.n_rows - 1 - n_y_, + ext_obs_t_.n_cols - 1); // extended observability matrix + + // This is what textbook (1996) says: + // + // Matrix Tr = join_vert(pinv(ext_obs_t_) * R_56_15, R_23_15); + // + // HOWEVER, do not know why but have to fill the last place with zeros like + // authors' matlab implementation (see `subid.m`) + // Otherwise, get ridiculous covariances (although A,C estimates are close to + // same...) + Matrix Tr = join_vert( + join_horiz(pinv(ext_obs_t_) * R_56_14, Matrix(n_x_, n_y_, fill::zeros)), + R_23_15); + Matrix Tl = join_vert(pinv(ext_obs_tm1) * R_66_15, R_55_15); + Matrix S = Tl * pinv(Tr); + + // Use alternative in van Overschee 1996, p. 129. Apparently, should ensure + // stability. + fit_.set_C(ext_obs_t_.submat(0, 0, n_y_ - 1, ext_obs_t_.n_cols - 1)); + Matrix ext_obs_t_p1 = join_vert( + ext_obs_t_.submat(n_y_, 0, ext_obs_t_.n_rows - 1, ext_obs_t_.n_cols - 1), + Matrix(n_y_, ext_obs_t_.n_cols, fill::zeros)); + fit_.set_A(pinv(ext_obs_t_) * ext_obs_t_p1); + + // At this point, van Overschee & de Moor suggest re-calculating ext_obs_t_, + // ext_obs_tm1 from (A, C) because it was just an approximation. This is + RecomputeExtObs(); + ext_obs_tm1 = ext_obs_t_.submat( + 0, 0, ext_obs_t_.n_rows - 1 - n_y_, + ext_obs_t_.n_cols - 1); // extended observability matrix + Tl = join_vert(pinv(ext_obs_tm1) * R_66_15, R_55_15); + Tr = join_vert( + join_horiz(pinv(ext_obs_t_) * R_56_14, Matrix(n_x_, n_y_, fill::zeros)), + R_23_15); + S = Tl * pinv(Tr); + + Matrix Lcurly = S.submat(0, 0, n_x_ + n_y_ - 1, n_x_ - 1) * pinv(ext_obs_t_); + Matrix Mcurly = pinv(ext_obs_tm1); + Matrix Pcurly = Tl - Lcurly * R_56_15; + Vector Pvec = vectorise(Pcurly); + Matrix Qcurly = R_23_15; + + // Identify [D; B], assuming D=0 and ensuring DC gain is correct + Matrix sum_QcurlyT_kron_Ncurly( + (n_h_ * (2 * n_u_ + n_y_) + n_y_) * (n_y_ + n_x_), n_u_ * (n_y_ + n_x_), + fill::zeros); + + Matrix eye_ext_obs_tm1(n_y_ + ext_obs_tm1.n_rows, n_y_ + ext_obs_tm1.n_cols, + fill::eye); + eye_ext_obs_tm1.submat(n_y_, n_y_, eye_ext_obs_tm1.n_rows - 1, + eye_ext_obs_tm1.n_cols - 1) = ext_obs_tm1; + + // van Overschee (1996) p. 126 + Matrix N1_Tl = -Lcurly; + N1_Tl.submat(0, 0, n_x_ - 1, N1_Tl.n_cols - 1) += + join_horiz(Matrix(n_x_, n_y_, fill::zeros), Mcurly); + N1_Tl.submat(n_x_, 0, n_x_ + n_y_ - 1, n_y_ - 1) += + Matrix(n_y_, n_y_, fill::eye); + + Matrix Nk_Tl(N1_Tl.n_rows, N1_Tl.n_cols, fill::zeros); + Matrix N_k; + for (size_t k = 0; k < n_h_; k++) { + auto Qcurly_k = + Qcurly.submat(n_u_ * k, 0, n_u_ * (k + 1) - 1, Qcurly.n_cols - 1); + + Nk_Tl.zeros(); + Nk_Tl.submat(0, 0, n_x_ + n_y_ - 1, Nk_Tl.n_cols - k * n_y_ - 1) = + N1_Tl.submat(0, k * n_y_, N1_Tl.n_rows - 1, N1_Tl.n_cols - 1); + N_k = Nk_Tl * eye_ext_obs_tm1; + + sum_QcurlyT_kron_Ncurly += kron(Qcurly_k.t(), N_k); + } + + Matrix err_vec; + if (wt_dc > 0) { + // Constraints enforced by weighted least squares + // + // Reference: + // + // Privara S, ..., Ferkl L_. (2010) Subspace Identification of Poorly + // Excited Industrial Systems. Conference in Decision and Control. + + // constraint 1: assume D=0 --> remove the components for Dvec (this is + // actually a hard constraint in that it ignores D) + Matrix sum_QcurlyT_kron_Ncurly_db = sum_QcurlyT_kron_Ncurly; + sum_QcurlyT_kron_Ncurly = + Matrix(sum_QcurlyT_kron_Ncurly_db.n_rows, n_x_ * n_u_); + + size_t kkk = 0; + for (size_t k = 1; k < (n_u_ + 1); k++) { + size_t start_idx = k * (n_y_ + n_x_) - n_x_; + for (size_t kk = 0; kk < n_x_; kk++) { + sum_QcurlyT_kron_Ncurly.col(kkk) = + sum_QcurlyT_kron_Ncurly_db.col(start_idx + kk); + kkk++; + } + } + + // constraint 2: Make sure DC I/O gain is correct + Matrix b_to_g0 = fit_.C() * inv(Matrix(n_x_, n_x_, fill::eye) - fit_.A()); + Matrix Pvec_Gvec = join_vert(Pvec, vectorise(g_dc_)); + Matrix eye_kron_b_to_g0 = kron(Matrix(n_u_, n_u_, fill::eye), b_to_g0); + Matrix sum_QcurlyT_kron_Ncurly_b_to_g0 = + join_vert(sum_QcurlyT_kron_Ncurly, eye_kron_b_to_g0); + + // WEIGHTED LS + // Important in practice because I care a lot about at least getting the DC + // gain correct. Put x weight on minimizing error at DC, relative to others + Matrix w(sum_QcurlyT_kron_Ncurly_b_to_g0.n_rows, + sum_QcurlyT_kron_Ncurly_b_to_g0.n_rows, fill::eye); + // Make weight on minimizing DC error immense so at least that + // should be nailed. + size_t start_row = sum_QcurlyT_kron_Ncurly.n_rows; + size_t start_col = sum_QcurlyT_kron_Ncurly.n_rows; + size_t stop_row = w.n_rows - 1; + size_t stop_col = w.n_cols - 1; + // w.submat(start_row, start_col, stop_row, stop_col) *= wt_dc*N;// scale + // weight with data length? + w.submat(start_row, start_col, stop_row, stop_col) *= wt_dc; + Vector b_vec = inv(sum_QcurlyT_kron_Ncurly_b_to_g0.t() * w * + sum_QcurlyT_kron_Ncurly_b_to_g0) * + sum_QcurlyT_kron_Ncurly_b_to_g0.t() * w * Pvec_Gvec; + + fit_.set_B(Matrix(b_vec.memptr(), n_x_, n_u_)); + + // Calculate residuals and their cov. + // Because I've added constraints, I need to re-calculate the right term + // with b_vec instead of how van Overschee do in final algorithm. + err_vec = Pvec - sum_QcurlyT_kron_Ncurly * b_vec; + } else { + // default way: *no* constraint on G0 or D=0 + Vector db_vec = pinv(sum_QcurlyT_kron_Ncurly) * Pvec; + // TODO(mfbolus) n.b., this gets thrown away... + // Matrix D = Matrix(db_vec.memptr(), n_y_, n_u_); + fit_.set_B(Matrix(db_vec.memptr() + (n_u_ * n_y_), n_x_, n_u_)); + err_vec = Pvec - sum_QcurlyT_kron_Ncurly * db_vec; + } + // Matrix err = Matrix(err_vec.memptr(), Pcurly.n_rows, Pcurly.n_cols); + + // TODO(mfbolus): Something is wrong with the error calculation above. + // Use the way van overschee does it in `subid.m` + // WARNING: this ignores any above constraints, so Q, R will be approximate... + Matrix err = Tl - S * Tr; + Matrix cov_err = err * err.t(); + fit_.set_Q(cov_err.submat(0, 0, n_x_ - 1, n_x_ - 1)); + fit_.set_R(cov_err.submat(n_x_, n_x_, n_x_ + n_y_ - 1, n_x_ + n_y_ - 1)); +} + +template +void SSID::RecomputeExtObs() { + ext_obs_t_.submat(0, 0, n_y_ - 1, ext_obs_t_.n_cols - 1) = fit_.C(); + for (size_t k = 2; k < (n_h_ + 1); k++) { + ext_obs_t_.submat((k - 1) * n_y_, 0, k * n_y_ - 1, ext_obs_t_.n_cols - 1) = + ext_obs_t_.submat((k - 2) * n_y_, 0, (k - 1) * n_y_ - 1, + ext_obs_t_.n_cols - 1) * + fit_.A(); + } +} + +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__gaussian_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__gaussian_8h.md index 51a85fdd..956c41c0 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__gaussian_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__gaussian_8h.md @@ -1,71 +1,71 @@ ---- -title: ldsCtrlEst_h/lds_gaussian.h -summary: glds namespace - ---- - -# ldsCtrlEst_h/lds_gaussian.h - -`glds` namespace [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | - -## Detailed Description - - - -This file declares and partially defines the namespace for linear dynamical systems with Gaussian observations (`[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)`). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_gaussian.h - LDS with Gaussian Output --*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_GAUSSIAN_H -#define LDSCTRLEST_LDS_GAUSSIAN_H - -// namespace -#include "lds.h" - -namespace lds { -namespace gaussian { -// insert any Gaussian-specific things here... -} // namespace gaussian -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_gaussian.h +summary: glds namespace + +--- + +# ldsCtrlEst_h/lds_gaussian.h + +`glds` namespace [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | + +## Detailed Description + + + +This file declares and partially defines the namespace for linear dynamical systems with Gaussian observations (`[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)`). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_gaussian.h - LDS with Gaussian Output --*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_GAUSSIAN_H +#define LDSCTRLEST_LDS_GAUSSIAN_H + +// namespace +#include "lds.h" + +namespace lds { +namespace gaussian { +// insert any Gaussian-specific things here... +} // namespace gaussian +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__ctrl_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__ctrl_8h.md index fafc590a..9b73e6f4 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__ctrl_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__ctrl_8h.md @@ -1,116 +1,116 @@ ---- -title: ldsCtrlEst_h/lds_gaussian_ctrl.h -summary: GLDS Controller. - ---- - -# ldsCtrlEst_h/lds_gaussian_ctrl.h - -GLDS Controller. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::gaussian::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1controller/)**
Gaussian-observation [Controller]() Type. | - -## Detailed Description - - - -This file declares and partially defines the type for control of a gaussian-observation linear dynamical system ([lds::gaussian::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1controller/)). It inherits functionality from the underlying GLDS model type ([lds::gaussian::System](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1system/)), including state estimation. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_gaussian_ctrl.h - GLDS Controller ------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_GAUSSIAN_CTRL_H -#define LDSCTRLEST_LDS_GAUSSIAN_CTRL_H - -// namespace -#include "lds_gaussian.h" -// system -#include "lds_gaussian_sys.h" -// controller -#include "lds_ctrl.h" - -namespace lds { -namespace gaussian { -class Controller : public lds::Controller { - public: - void set_y_ref(const Vector& y_ref) override { - Reassign(y_ref_,y_ref); - cx_ref_ = y_ref - sys_.d(); - }; - - // make sure base class template methods available - using lds::Controller::Controller; - using lds::Controller::Control; - using lds::Controller::ControlOutputReference; - - using lds::Controller::sys; - using lds::Controller::Kc; - using lds::Controller::Kc_inty; - using lds::Controller::Kc_u; - using lds::Controller::g_design; - using lds::Controller::u_ref; - using lds::Controller::x_ref; - using lds::Controller::y_ref; - using lds::Controller::control_type; - - using lds::Controller::set_sys; - using lds::Controller::set_g_design; - using lds::Controller::set_u_ref; - using lds::Controller::set_x_ref; - using lds::Controller::set_y_ref; - using lds::Controller::set_Kc; - using lds::Controller::set_Kc_inty; - using lds::Controller::set_Kc_u; - using lds::Controller::set_tau_awu; - using lds::Controller::set_control_type; - - using lds::Controller::Reset; - using lds::Controller::Print; -}; -} // namespace gaussian -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_gaussian_ctrl.h +summary: GLDS Controller. + +--- + +# ldsCtrlEst_h/lds_gaussian_ctrl.h + +GLDS Controller. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::gaussian::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_controller/)**
Gaussian-observation [Controller]() Type. | + +## Detailed Description + + + +This file declares and partially defines the type for control of a gaussian-observation linear dynamical system ([lds::gaussian::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_controller/)). It inherits functionality from the underlying GLDS model type ([lds::gaussian::System](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_system/)), including state estimation. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_gaussian_ctrl.h - GLDS Controller ------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_GAUSSIAN_CTRL_H +#define LDSCTRLEST_LDS_GAUSSIAN_CTRL_H + +// namespace +#include "lds_gaussian.h" +// system +#include "lds_gaussian_sys.h" +// controller +#include "lds_ctrl.h" + +namespace lds { +namespace gaussian { +class Controller : public lds::Controller { + public: + void set_y_ref(const Vector& y_ref) override { + Reassign(y_ref_,y_ref); + cx_ref_ = y_ref - sys_.d(); + }; + + // make sure base class template methods available + using lds::Controller::Controller; + using lds::Controller::Control; + using lds::Controller::ControlOutputReference; + + using lds::Controller::sys; + using lds::Controller::Kc; + using lds::Controller::Kc_inty; + using lds::Controller::Kc_u; + using lds::Controller::g_design; + using lds::Controller::u_ref; + using lds::Controller::x_ref; + using lds::Controller::y_ref; + using lds::Controller::control_type; + + using lds::Controller::set_sys; + using lds::Controller::set_g_design; + using lds::Controller::set_u_ref; + using lds::Controller::set_x_ref; + using lds::Controller::set_y_ref; + using lds::Controller::set_Kc; + using lds::Controller::set_Kc_inty; + using lds::Controller::set_Kc_u; + using lds::Controller::set_tau_awu; + using lds::Controller::set_control_type; + + using lds::Controller::Reset; + using lds::Controller::Print; +}; +} // namespace gaussian +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit_8h.md index cff73443..32eba79e 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit_8h.md @@ -1,94 +1,94 @@ ---- -title: ldsCtrlEst_h/lds_gaussian_fit.h -summary: GLDS fit type. - ---- - -# ldsCtrlEst_h/lds_gaussian_fit.h - -GLDS fit type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::gaussian::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fit/)**
GLDS [Fit]() Type. | - -## Detailed Description - - - -This file declares and partially defines the base fit type for a Gaussian-output linear dynamical system. Models are fit by either subspace identification (SSID) or expectation-maximization (EM). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_gaussian_fit.h - Fit Type for GLDS -----*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_GAUSSIAN_FIT_H -#define LDSCTRLEST_LDS_GAUSSIAN_FIT_H - -// namespace -#include "lds_gaussian.h" -// fit type -#include "lds_fit.h" - -namespace lds { -namespace gaussian { -class Fit : public lds::Fit { - public: - Fit() = default; - - Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt); - const Matrix& R() const override { return R_; }; - void set_R(const Matrix& R) override { - Reassign(R_, R); - ForceSymPD(R_); - }; - - View h(Matrix& y, const Matrix& x, size_t t) override { - y.col(t) = C_ * x.col(t) + d_; - return y.col(t); - }; -}; - -}; // namespace gaussian -} // namespace lds -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_gaussian_fit.h +summary: GLDS fit type. + +--- + +# ldsCtrlEst_h/lds_gaussian_fit.h + +GLDS fit type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::gaussian::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit/)**
GLDS [Fit]() Type. | + +## Detailed Description + + + +This file declares and partially defines the base fit type for a Gaussian-output linear dynamical system. Models are fit by either subspace identification (SSID) or expectation-maximization (EM). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_gaussian_fit.h - Fit Type for GLDS -----*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_GAUSSIAN_FIT_H +#define LDSCTRLEST_LDS_GAUSSIAN_FIT_H + +// namespace +#include "lds_gaussian.h" +// fit type +#include "lds_fit.h" + +namespace lds { +namespace gaussian { +class Fit : public lds::Fit { + public: + Fit() = default; + + Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt); + const Matrix& R() const override { return R_; }; + void set_R(const Matrix& R) override { + Reassign(R_, R); + ForceSymPD(R_); + }; + + View h(Matrix& y, const Matrix& x, size_t t) override { + y.col(t) = C_ * x.col(t) + d_; + return y.col(t); + }; +}; + +}; // namespace gaussian +} // namespace lds +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit__em_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit__em_8h.md index 68ad2306..68d0f405 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit__em_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit__em_8h.md @@ -1,92 +1,92 @@ ---- -title: ldsCtrlEst_h/lds_gaussian_fit_em.h -summary: GLDS E-M fit type. - ---- - -# ldsCtrlEst_h/lds_gaussian_fit_em.h - -GLDS E-M fit type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::gaussian::FitEM](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fitem/)**
GLDS E-M [Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fit/) Type. | - -## Detailed Description - - - -This file declares and partially defines a type by which Gaussian-output LDS models are fit by the expectation-maximization (EM) algorithm (`lds::gaussian::emFit_t`). - -References: [1] Shumway RH, Stoffer DS. (1982) An Approach to Time Series Smoothing and Forecasting Using the EM Algorithm.Journal of Time Series Analysis 3(2). - -[2] Ghahramani Z, Hinton GE. (1996) Parameter Estimation for Linear Dynamical Systems. Technical Report CRG-TR-96-2. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_gaussian_fit_em.h - GLDS Fit (EM) ------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_GAUSSIAN_FIT_EM_H -#define LDSCTRLEST_LDS_GAUSSIAN_FIT_EM_H - -#include "lds_fit_em.h" -#include "lds_gaussian_fit.h" - -namespace lds { -namespace gaussian { -class FitEM : public EM { - public: - using EM::EM; - - private: - void MaximizeOutput() override; - - void MaximizeMeasurement() override; - - void RecurseKe(Matrix& Ke, Cube& P_pre, Cube& P_post, size_t t) override; -}; - -} // namespace gaussian -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_gaussian_fit_em.h +summary: GLDS E-M fit type. + +--- + +# ldsCtrlEst_h/lds_gaussian_fit_em.h + +GLDS E-M fit type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::gaussian::FitEM](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit_e_m/)**
GLDS E-M [Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit/) Type. | + +## Detailed Description + + + +This file declares and partially defines a type by which Gaussian-output LDS models are fit by the expectation-maximization (EM) algorithm (`lds::gaussian::emFit_t`). + +References: [1] Shumway RH, Stoffer DS. (1982) An Approach to Time Series Smoothing and Forecasting Using the EM Algorithm.Journal of Time Series Analysis 3(2). + +[2] Ghahramani Z, Hinton GE. (1996) Parameter Estimation for Linear Dynamical Systems. Technical Report CRG-TR-96-2. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_gaussian_fit_em.h - GLDS Fit (EM) ------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_GAUSSIAN_FIT_EM_H +#define LDSCTRLEST_LDS_GAUSSIAN_FIT_EM_H + +#include "lds_fit_em.h" +#include "lds_gaussian_fit.h" + +namespace lds { +namespace gaussian { +class FitEM : public EM { + public: + using EM::EM; + + private: + void MaximizeOutput() override; + + void MaximizeMeasurement() override; + + void RecurseKe(Matrix& Ke, Cube& P_pre, Cube& P_post, size_t t) override; +}; + +} // namespace gaussian +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit__ssid_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit__ssid_8h.md index 9379f5f2..f6f66575 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit__ssid_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__fit__ssid_8h.md @@ -1,91 +1,91 @@ ---- -title: ldsCtrlEst_h/lds_gaussian_fit_ssid.h -summary: GLDS SSID fit type. - ---- - -# ldsCtrlEst_h/lds_gaussian_fit_ssid.h - -GLDS SSID fit type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::gaussian::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fitssid/)**
Subspace Identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1ssid/)) for GLDS. | - -## Detailed Description - - - -This file declares and partially defines a type by which Gaussian-output LDS models are fit by a subspace identification (SSID) algorithm (`lds::gaussian::ssidFit_t`). - -References: [1] van Overschee P, de Moore B. (1996) Subspace Identification for Linear Systems. Boston: Springer. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_gaussian_fit_ssid.h - GLDS Fit (SSID) --*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_GAUSSIAN_FIT_SSID_H -#define LDSCTRLEST_LDS_GAUSSIAN_FIT_SSID_H - -#include "lds_fit_ssid.h" -#include "lds_gaussian_fit.h" - -namespace lds { -namespace gaussian { -class FitSSID : public SSID { - public: - using SSID::SSID; - using SSID::Run; - - private: - using SSID::CreateHankelDataMat; - using SSID::CalcSVD; - using SSID::Solve; - - void DecomposeData() override; - - void SolveVanOverschee(); -}; -} // namespace gaussian -} // namespace lds -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_gaussian_fit_ssid.h +summary: GLDS SSID fit type. + +--- + +# ldsCtrlEst_h/lds_gaussian_fit_ssid.h + +GLDS SSID fit type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::gaussian::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit_s_s_i_d/)**
Subspace Identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1_s_s_i_d/)) for GLDS. | + +## Detailed Description + + + +This file declares and partially defines a type by which Gaussian-output LDS models are fit by a subspace identification (SSID) algorithm (`lds::gaussian::ssidFit_t`). + +References: [1] van Overschee P, de Moore B. (1996) Subspace Identification for Linear Systems. Boston: Springer. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_gaussian_fit_ssid.h - GLDS Fit (SSID) --*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_GAUSSIAN_FIT_SSID_H +#define LDSCTRLEST_LDS_GAUSSIAN_FIT_SSID_H + +#include "lds_fit_ssid.h" +#include "lds_gaussian_fit.h" + +namespace lds { +namespace gaussian { +class FitSSID : public SSID { + public: + using SSID::SSID; + using SSID::Run; + + private: + using SSID::CreateHankelDataMat; + using SSID::CalcSVD; + using SSID::Solve; + + void DecomposeData() override; + + void SolveVanOverschee(); +}; +} // namespace gaussian +} // namespace lds +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sctrl_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sctrl_8h.md index 338d66db..898ece20 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sctrl_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sctrl_8h.md @@ -1,114 +1,114 @@ ---- -title: ldsCtrlEst_h/lds_gaussian_sctrl.h -summary: GLDS switched controller type. - ---- - -# ldsCtrlEst_h/lds_gaussian_sctrl.h - -GLDS switched controller type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::gaussian::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1switchedcontroller/)**
Gaussian-observation [SwitchedController]() Type. | - -## Detailed Description - - - -This file declares and partially defines the type for switched feedback control of a system approximated as multiple discrete Gaussian-output linear dynamical systems ([lds::gaussian::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1switchedcontroller/)). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_gaussian_sctrl.h - Switched Controller -*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_GAUSSIAN_SCTRL_H -#define LDSCTRLEST_LDS_GAUSSIAN_SCTRL_H - -// controller type -#include "lds_gaussian_ctrl.h" -// switched controller -#include "lds_sctrl.h" - -namespace lds { -namespace gaussian { -class SwitchedController : public lds::SwitchedController { - public: - void set_y_ref(const Vector& y_ref) override { - Reassign(y_ref_, y_ref); - cx_ref_ = y_ref - sys_.d(); - } - - // make sure base class template methods available - using lds::SwitchedController::SwitchedController; - using lds::SwitchedController::Switch; - using lds::SwitchedController::Control; - using lds::SwitchedController::ControlOutputReference; - - using lds::SwitchedController::sys; - using lds::SwitchedController::Kc; - using lds::SwitchedController::Kc_inty; - using lds::SwitchedController::Kc_u; - using lds::SwitchedController::g_design; - using lds::SwitchedController::u_ref; - using lds::SwitchedController::x_ref; - using lds::SwitchedController::y_ref; - using lds::SwitchedController::control_type; - - using lds::SwitchedController::set_g_design; - using lds::SwitchedController::set_u_ref; - using lds::SwitchedController::set_x_ref; - using lds::SwitchedController::set_y_ref; - using lds::SwitchedController::set_Kc; - using lds::SwitchedController::set_Kc_inty; - using lds::SwitchedController::set_Kc_u; - using lds::SwitchedController::set_tau_awu; - using lds::SwitchedController::set_control_type; - - using lds::SwitchedController::Reset; - using lds::SwitchedController::Print; -}; // SwitchedController -} // namespace gaussian -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_gaussian_sctrl.h +summary: GLDS switched controller type. + +--- + +# ldsCtrlEst_h/lds_gaussian_sctrl.h + +GLDS switched controller type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::gaussian::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_switched_controller/)**
Gaussian-observation [SwitchedController]() Type. | + +## Detailed Description + + + +This file declares and partially defines the type for switched feedback control of a system approximated as multiple discrete Gaussian-output linear dynamical systems ([lds::gaussian::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_switched_controller/)). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_gaussian_sctrl.h - Switched Controller -*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_GAUSSIAN_SCTRL_H +#define LDSCTRLEST_LDS_GAUSSIAN_SCTRL_H + +// controller type +#include "lds_gaussian_ctrl.h" +// switched controller +#include "lds_sctrl.h" + +namespace lds { +namespace gaussian { +class SwitchedController : public lds::SwitchedController { + public: + void set_y_ref(const Vector& y_ref) override { + Reassign(y_ref_, y_ref); + cx_ref_ = y_ref - sys_.d(); + } + + // make sure base class template methods available + using lds::SwitchedController::SwitchedController; + using lds::SwitchedController::Switch; + using lds::SwitchedController::Control; + using lds::SwitchedController::ControlOutputReference; + + using lds::SwitchedController::sys; + using lds::SwitchedController::Kc; + using lds::SwitchedController::Kc_inty; + using lds::SwitchedController::Kc_u; + using lds::SwitchedController::g_design; + using lds::SwitchedController::u_ref; + using lds::SwitchedController::x_ref; + using lds::SwitchedController::y_ref; + using lds::SwitchedController::control_type; + + using lds::SwitchedController::set_g_design; + using lds::SwitchedController::set_u_ref; + using lds::SwitchedController::set_x_ref; + using lds::SwitchedController::set_y_ref; + using lds::SwitchedController::set_Kc; + using lds::SwitchedController::set_Kc_inty; + using lds::SwitchedController::set_Kc_u; + using lds::SwitchedController::set_tau_awu; + using lds::SwitchedController::set_control_type; + + using lds::SwitchedController::Reset; + using lds::SwitchedController::Print; +}; // SwitchedController +} // namespace gaussian +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sys_8cpp.md b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sys_8cpp.md index 0cbdc0f3..c87f50a6 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sys_8cpp.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sys_8cpp.md @@ -1,98 +1,98 @@ ---- -title: src/lds_gaussian_sys.cpp -summary: GLDS base type. - ---- - -# src/lds_gaussian_sys.cpp - -GLDS base type. [More...](#detailed-description) - - - -## Detailed Description - - - -This file implements the type for state estimation (filtering) as well as simulation of Gaussian-output linear dynamical systems (`lds::gaussian::sys_t`). It inherits functionality from the underlying linear dynamical system (`lds::sys_t`). - - - - - -## Source code - -```cpp -//===-- lds_gaussian_sys.cpp - GLDS ---------------------------------------===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#include - -lds::gaussian::System::System(size_t n_u, size_t n_x, size_t n_y, data_t dt, data_t p0, - data_t q0, data_t r0) - : lds::System(n_u, n_x, n_y, dt, p0, q0) { - - R_.zeros(n_y, n_y); - R_.diag().fill(r0); - - do_recurse_Ke_=true; -}; - -// recursively estimate Ke -void lds::gaussian::System::RecurseKe() { - if (!do_recurse_Ke_) { - return; - } - - // predict covariance - P_ = A_ * P_ * A_.t() + Q_; - - // calc Kalman gain - Ke_ = P_ * C_.t() * inv_sympd(C_ * P_ * C_.t() + R_); - - // update covariance - // Reference: Ghahramani et Hinton (1996) - P_ = P_ - Ke_ * C_ * P_; - - if (do_adapt_m) { - P_m_ += Q_m_; // A_m = I (i.e., random walk) - Ke_m_ = P_m_ * C_.t() * inv_sympd(C_ * P_m_ * C_.t() + R_); - P_m_ = P_m_ - Ke_m_ * C_ * P_m_; - } -} - -// Simulate -const lds::Vector& lds::gaussian::System::Simulate(const Vector& u_tm1){ - f(u_tm1, true);//simulate dynamics with noise added - h();//output - z_ = y_ + arma::mvnrnd(Vector(n_y_).fill(0), R_);//measure - return z_; -} - -void lds::gaussian::System::Print() { - lds::System::Print(); - std::cout << "R: \n" << R_ << "\n"; -} -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: src/lds_gaussian_sys.cpp +summary: GLDS base type. + +--- + +# src/lds_gaussian_sys.cpp + +GLDS base type. [More...](#detailed-description) + + + +## Detailed Description + + + +This file implements the type for state estimation (filtering) as well as simulation of Gaussian-output linear dynamical systems (`lds::gaussian::sys_t`). It inherits functionality from the underlying linear dynamical system (`lds::sys_t`). + + + + + +## Source code + +```cpp +//===-- lds_gaussian_sys.cpp - GLDS ---------------------------------------===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#include + +lds::gaussian::System::System(size_t n_u, size_t n_x, size_t n_y, data_t dt, data_t p0, + data_t q0, data_t r0) + : lds::System(n_u, n_x, n_y, dt, p0, q0) { + + R_.zeros(n_y, n_y); + R_.diag().fill(r0); + + do_recurse_Ke_=true; +}; + +// recursively estimate Ke +void lds::gaussian::System::RecurseKe() { + if (!do_recurse_Ke_) { + return; + } + + // predict covariance + P_ = A_ * P_ * A_.t() + Q_; + + // calc Kalman gain + Ke_ = P_ * C_.t() * inv_sympd(C_ * P_ * C_.t() + R_); + + // update covariance + // Reference: Ghahramani et Hinton (1996) + P_ = P_ - Ke_ * C_ * P_; + + if (do_adapt_m) { + P_m_ += Q_m_; // A_m = I (i.e., random walk) + Ke_m_ = P_m_ * C_.t() * inv_sympd(C_ * P_m_ * C_.t() + R_); + P_m_ = P_m_ - Ke_m_ * C_ * P_m_; + } +} + +// Simulate +const lds::Vector& lds::gaussian::System::Simulate(const Vector& u_tm1){ + f(u_tm1, true);//simulate dynamics with noise added + h();//output + z_ = y_ + arma::mvnrnd(Vector(n_y_).fill(0), R_);//measure + return z_; +} + +void lds::gaussian::System::Print() { + lds::System::Print(); + std::cout << "R: \n" << R_ << "\n"; +} +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sys_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sys_8h.md index 7649b701..f7b75fa2 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sys_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__gaussian__sys_8h.md @@ -1,126 +1,128 @@ ---- -title: ldsCtrlEst_h/lds_gaussian_sys.h -summary: GLDS base type. - ---- - -# ldsCtrlEst_h/lds_gaussian_sys.h - -GLDS base type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::gaussian::System](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1system/)**
Gaussian LDS Type. | - -## Detailed Description - - - -This file declares and partially defines the type for state estimation (filtering) as well as simulation of Gaussian-output linear dynamical systems (`[lds::gaussian::System](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1system/)`). It inherits functionality from the underlying linear dynamical system (`[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1system/)`). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_gaussian_sys.h - GLDS ------------------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_GAUSSIAN_SYS_H -#define LDSCTRLEST_LDS_GAUSSIAN_SYS_H - -// namespace -#include "lds_gaussian.h" -// system -#include "lds_sys.h" - -namespace lds { -namespace gaussian { -class System : public lds::System { - public: - System() = default; - - System(std::size_t n_u, std::size_t n_x, std::size_t n_y, data_t dt, - data_t p0 = kDefaultP0, data_t q0 = kDefaultQ0, - data_t r0 = kDefaultR0); - - const Vector& Simulate(const Vector& u_tm1) override; - - // get methods - const Matrix& R() const { return R_; }; - - // set methods - void set_Q(const Matrix& Q) { - lds::System::set_Q(Q); - do_recurse_Ke_ = true; - } - void set_R(const Matrix& R) { - Reassign(R_,R); - do_recurse_Ke_ = true; - }; - - void set_Ke(const Matrix& Ke) { - Reassign(Ke_,Ke); - // if users have set Ke, they must not want to calculate it online. - do_recurse_Ke_ = false; - }; - void set_Ke_m(const Matrix& Ke_m) { - Reassign(Ke_m_,Ke_m); - // if users have set Ke, they must not want to calculate it online. - do_recurse_Ke_ = false; - }; - - void Print(); - - protected: - void h() override { - cx_ = C_ * x_; - y_ = cx_ + d_; - }; - - void RecurseKe() override; - - // Gaussian-output-specific - Matrix R_; - bool do_recurse_Ke_{}; -}; // System -} // namespace gaussian -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_gaussian_sys.h +summary: GLDS base type. + +--- + +# ldsCtrlEst_h/lds_gaussian_sys.h + +GLDS base type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::gaussian::System](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_system/)**
Gaussian LDS Type. | + +## Detailed Description + + + +This file declares and partially defines the type for state estimation (filtering) as well as simulation of Gaussian-output linear dynamical systems (`[lds::gaussian::System](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_system/)`). It inherits functionality from the underlying linear dynamical system (`[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1_system/)`). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_gaussian_sys.h - GLDS ------------------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_GAUSSIAN_SYS_H +#define LDSCTRLEST_LDS_GAUSSIAN_SYS_H + +// namespace +#include "lds_gaussian.h" +// system +#include "lds_sys.h" + +namespace lds { +namespace gaussian { +class System : public lds::System { + public: + System() = default; + + System(std::size_t n_u, std::size_t n_x, std::size_t n_y, data_t dt, + data_t p0 = kDefaultP0, data_t q0 = kDefaultQ0, + data_t r0 = kDefaultR0); + + const Vector& Simulate(const Vector& u_tm1) override; + + // get methods + const Matrix& R() const { return R_; }; + + // set methods + void set_Q(const Matrix& Q) { + lds::System::set_Q(Q); + do_recurse_Ke_ = true; + } + void set_R(const Matrix& R) { + Reassign(R_, R); + do_recurse_Ke_ = true; + }; + + void set_Ke(const Matrix& Ke) { + Reassign(Ke_, Ke); + // if users have set Ke, they must not want to calculate it online. + do_recurse_Ke_ = false; + }; + void set_Ke_m(const Matrix& Ke_m) { + Reassign(Ke_m_, Ke_m); + // if users have set Ke, they must not want to calculate it online. + do_recurse_Ke_ = false; + }; + + void Print(); + + protected: + void h() override { + cx_ = C_ * x_; + y_ = cx_ + d_; + }; + + Vector h_(Vector x) override { return C_ * x + d_; }; + + void RecurseKe() override; + + // Gaussian-output-specific + Matrix R_; + bool do_recurse_Ke_{}; +}; // System +} // namespace gaussian +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__poisson_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__poisson_8h.md index bf41756f..e60406ee 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__poisson_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__poisson_8h.md @@ -1,75 +1,75 @@ ---- -title: ldsCtrlEst_h/lds_poisson.h -summary: plds namespace - ---- - -# ldsCtrlEst_h/lds_poisson.h - -`plds` namespace [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | - -## Detailed Description - - - -This file declares and partially defines the namespace for linear dynamical systems with Poisson observations (`[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)`). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_poisson.h - LDS with Poisson Output ----*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_POISSON_H -#define LDSCTRLEST_LDS_POISSON_H - -#include "lds.h" - -namespace lds { -namespace poisson { -// TODO(mfbolus): Not sure if defining these as static here makes the most -// sense. Is there a downside to letting multiple poisson System objects share a -// common random number generator? -static std::random_device rd; -static std::mt19937 rng = std::mt19937( - rd()); -} // namespace poisson -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_poisson.h +summary: plds namespace + +--- + +# ldsCtrlEst_h/lds_poisson.h + +`plds` namespace [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | + +## Detailed Description + + + +This file declares and partially defines the namespace for linear dynamical systems with Poisson observations (`[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)`). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_poisson.h - LDS with Poisson Output ----*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_POISSON_H +#define LDSCTRLEST_LDS_POISSON_H + +#include "lds.h" + +namespace lds { +namespace poisson { +// TODO(mfbolus): Not sure if defining these as static here makes the most +// sense. Is there a downside to letting multiple poisson System objects share a +// common random number generator? +static std::random_device rd; +static std::mt19937 rng = std::mt19937( + rd()); +} // namespace poisson +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__poisson__ctrl_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__poisson__ctrl_8h.md index fa6691c7..2734bfa5 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__poisson__ctrl_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__poisson__ctrl_8h.md @@ -1,121 +1,121 @@ ---- -title: ldsCtrlEst_h/lds_poisson_ctrl.h -summary: PLDS controller type. - ---- - -# ldsCtrlEst_h/lds_poisson_ctrl.h - -PLDS controller type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::poisson::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1controller/)**
PLDS [Controller]() Type. | - -## Detailed Description - - - -This file declares and partially defines the type for feedback control of a Poisson-output linear dynamical system (`[lds::poisson::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1controller/)`). It inherits functionality from the underlying PLDS model type (`[lds::poisson::System](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1system/)`), including state estimation. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_poisson_ctrl.h - PLDS Controller -------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_POISSON_CTRL_H -#define LDSCTRLEST_LDS_POISSON_CTRL_H - -// namespace -#include "lds_poisson.h" -// system type -#include "lds_poisson_sys.h" -// control type -#include "lds_ctrl.h" - -namespace lds { -namespace poisson { -class Controller : public lds::Controller { - public: - void set_y_ref(const Vector& y_ref) override { - Reassign(y_ref_, y_ref); - lds::Limit(y_ref_, kYRefLb, lds::kInf); - cx_ref_ = log(y_ref_) - sys_.d(); - }; - - // make sure base class template methods available - using lds::Controller::Controller; - using lds::Controller::Control; - using lds::Controller::ControlOutputReference; - - using lds::Controller::sys; - using lds::Controller::Kc; - using lds::Controller::Kc_inty; - using lds::Controller::Kc_u; - using lds::Controller::g_design; - using lds::Controller::u_ref; - using lds::Controller::x_ref; - using lds::Controller::y_ref; - using lds::Controller::control_type; - - using lds::Controller::set_sys; - using lds::Controller::set_g_design; - using lds::Controller::set_u_ref; - using lds::Controller::set_x_ref; - using lds::Controller::set_y_ref; - using lds::Controller::set_Kc; - using lds::Controller::set_Kc_inty; - using lds::Controller::set_Kc_u; - using lds::Controller::set_tau_awu; - using lds::Controller::set_control_type; - - using lds::Controller::Reset; - using lds::Controller::Print; - - private: - constexpr static const data_t kYRefLb = - 1e-4; -}; -} // namespace poisson -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_poisson_ctrl.h +summary: PLDS controller type. + +--- + +# ldsCtrlEst_h/lds_poisson_ctrl.h + +PLDS controller type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::poisson::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_controller/)**
PLDS [Controller]() Type. | + +## Detailed Description + + + +This file declares and partially defines the type for feedback control of a Poisson-output linear dynamical system (`[lds::poisson::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_controller/)`). It inherits functionality from the underlying PLDS model type (`[lds::poisson::System](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_system/)`), including state estimation. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_poisson_ctrl.h - PLDS Controller -------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_POISSON_CTRL_H +#define LDSCTRLEST_LDS_POISSON_CTRL_H + +// namespace +#include "lds_poisson.h" +// system type +#include "lds_poisson_sys.h" +// control type +#include "lds_ctrl.h" + +namespace lds { +namespace poisson { +class Controller : public lds::Controller { + public: + void set_y_ref(const Vector& y_ref) override { + Reassign(y_ref_, y_ref); + lds::Limit(y_ref_, kYRefLb, lds::kInf); + cx_ref_ = log(y_ref_) - sys_.d(); + }; + + // make sure base class template methods available + using lds::Controller::Controller; + using lds::Controller::Control; + using lds::Controller::ControlOutputReference; + + using lds::Controller::sys; + using lds::Controller::Kc; + using lds::Controller::Kc_inty; + using lds::Controller::Kc_u; + using lds::Controller::g_design; + using lds::Controller::u_ref; + using lds::Controller::x_ref; + using lds::Controller::y_ref; + using lds::Controller::control_type; + + using lds::Controller::set_sys; + using lds::Controller::set_g_design; + using lds::Controller::set_u_ref; + using lds::Controller::set_x_ref; + using lds::Controller::set_y_ref; + using lds::Controller::set_Kc; + using lds::Controller::set_Kc_inty; + using lds::Controller::set_Kc_u; + using lds::Controller::set_tau_awu; + using lds::Controller::set_control_type; + + using lds::Controller::Reset; + using lds::Controller::Print; + + private: + constexpr static const data_t kYRefLb = + 1e-4; +}; +} // namespace poisson +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit_8h.md index 144d1b6b..444c7814 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit_8h.md @@ -1,102 +1,102 @@ ---- -title: ldsCtrlEst_h/lds_poisson_fit.h -summary: PLDS base fit type. - ---- - -# ldsCtrlEst_h/lds_poisson_fit.h - -PLDS base fit type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::poisson::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1fit/)**
PLDS [Fit]() Type. | - -## Detailed Description - - - -This file declares and partially defines the base fit type for a Gaussian-output linear dynamical system. Models are fit by either subspace identification (SSID) or expectation-maximization (EM). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_poisson_fit.h - Fit Type for PLDS ------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_POISSON_FIT_H -#define LDSCTRLEST_LDS_POISSON_FIT_H - -// namespace -#include "lds_poisson.h" -// fit -#include "lds_fit.h" - -namespace lds { -namespace poisson { -class Fit : public lds::Fit { - public: - Fit() = default; - - Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt) - : lds::Fit(n_u, n_x, n_y, dt){}; - - View h(Matrix& y, const Matrix& x, size_t t) override { - y.col(t) = exp(C_ * x.col(t) + d_); - return y.col(t); - }; - - void set_R(const Matrix& R) override { - std::cerr - << "WARNING: Cannot set R (R[0] = " << R.at(0) - << "). No Gaussian measurement noise in Poisson observation model.\n"; - }; - - const Matrix& R() const override { - return R_; - }; - -}; - -}; // namespace poisson -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_poisson_fit.h +summary: PLDS base fit type. + +--- + +# ldsCtrlEst_h/lds_poisson_fit.h + +PLDS base fit type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::poisson::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_fit/)**
PLDS [Fit]() Type. | + +## Detailed Description + + + +This file declares and partially defines the base fit type for a Gaussian-output linear dynamical system. Models are fit by either subspace identification (SSID) or expectation-maximization (EM). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_poisson_fit.h - Fit Type for PLDS ------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_POISSON_FIT_H +#define LDSCTRLEST_LDS_POISSON_FIT_H + +// namespace +#include "lds_poisson.h" +// fit +#include "lds_fit.h" + +namespace lds { +namespace poisson { +class Fit : public lds::Fit { + public: + Fit() = default; + + Fit(size_t n_u, size_t n_x, size_t n_y, data_t dt) + : lds::Fit(n_u, n_x, n_y, dt){}; + + View h(Matrix& y, const Matrix& x, size_t t) override { + y.col(t) = exp(C_ * x.col(t) + d_); + return y.col(t); + }; + + void set_R(const Matrix& R) override { + std::cerr + << "WARNING: Cannot set R (R[0] = " << R.at(0) + << "). No Gaussian measurement noise in Poisson observation model.\n"; + }; + + const Matrix& R() const override { + return R_; + }; + +}; + +}; // namespace poisson +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit__em_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit__em_8h.md index 86a2ab2c..2cffe345 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit__em_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit__em_8h.md @@ -1,98 +1,98 @@ ---- -title: ldsCtrlEst_h/lds_poisson_fit_em.h -summary: PLDS E-M fit type. - ---- - -# ldsCtrlEst_h/lds_poisson_fit_em.h - -PLDS E-M fit type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::poisson::FitEM](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1fitem/)**
PLDS E-M [Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1fit/) Type. | - -## Detailed Description - - - -This file declares and partially defines a type by which Gaussian-output LDS models are fit by the expectation-maximization (EM) algorithm (`lds::gaussian::emFit_t`). - -References: [1] Shumway RH, Stoffer DS. (1982) An Approach to Time Series Smoothing and Forecasting Using the EM Algorithm.Journal of Time Series Analysis 3(2). - -[2] Ghahramani Z, Hinton GE. (1996) Parameter Estimation for Linear Dynamical Systems. Technical Report CRG-TR-96-2. - -[3] Smith A, Brown E. (2003) Estimating a State-Space Model from Point Process Observations. Neural Computation. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_poisson_fit_em.h - PLDS Fit (EM) -------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_POISSON_FIT_EM_H -#define LDSCTRLEST_LDS_POISSON_FIT_EM_H - -#include "lds_fit_em.h" -#include "lds_poisson_fit.h" - -namespace lds { -namespace poisson { -class FitEM : public EM { - public: - using EM::EM; - - private: - void MaximizeOutput() override; - - void MaximizeMeasurement() override{}; - - void RecurseKe(Matrix& Ke, Cube& P_pre, Cube& P_post, size_t t) override; - - data_t NewtonSolveC(); - - void AnalyticalSolveD(); -}; - -} // namespace poisson -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_poisson_fit_em.h +summary: PLDS E-M fit type. + +--- + +# ldsCtrlEst_h/lds_poisson_fit_em.h + +PLDS E-M fit type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::poisson::FitEM](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_fit_e_m/)**
PLDS E-M [Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_fit/) Type. | + +## Detailed Description + + + +This file declares and partially defines a type by which Gaussian-output LDS models are fit by the expectation-maximization (EM) algorithm (`lds::gaussian::emFit_t`). + +References: [1] Shumway RH, Stoffer DS. (1982) An Approach to Time Series Smoothing and Forecasting Using the EM Algorithm.Journal of Time Series Analysis 3(2). + +[2] Ghahramani Z, Hinton GE. (1996) Parameter Estimation for Linear Dynamical Systems. Technical Report CRG-TR-96-2. + +[3] Smith A, Brown E. (2003) Estimating a State-Space Model from Point Process Observations. Neural Computation. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_poisson_fit_em.h - PLDS Fit (EM) -------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_POISSON_FIT_EM_H +#define LDSCTRLEST_LDS_POISSON_FIT_EM_H + +#include "lds_fit_em.h" +#include "lds_poisson_fit.h" + +namespace lds { +namespace poisson { +class FitEM : public EM { + public: + using EM::EM; + + private: + void MaximizeOutput() override; + + void MaximizeMeasurement() override{}; + + void RecurseKe(Matrix& Ke, Cube& P_pre, Cube& P_post, size_t t) override; + + data_t NewtonSolveC(); + + void AnalyticalSolveD(); +}; + +} // namespace poisson +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit__ssid_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit__ssid_8h.md index dd806216..4460abbe 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit__ssid_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__poisson__fit__ssid_8h.md @@ -1,90 +1,90 @@ ---- -title: ldsCtrlEst_h/lds_poisson_fit_ssid.h -summary: PLDS SSID fit type. - ---- - -# ldsCtrlEst_h/lds_poisson_fit_ssid.h - -PLDS SSID fit type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::poisson::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1fitssid/)**
Subspace Identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1ssid/)) for PLDS. | - -## Detailed Description - - - -This file declares and partially defines a type by which Poisson-output LDS models are fit by a subspace identification (SSID) algorithm (`[lds::gaussian::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fitssid/)`). - -References: [1] van Overschee P, de Moore B. (1996) Subspace Identification for Linear Systems. Boston: Springer. [2] Buesing L, Macke JH, Sahani M. (2012) Spectral learning of linear dynamics from generalised-linear observations with application to neural population data. NIPS 25. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_poisson_fit_ssid.h - PLDS Fit (SSID) ---*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_POISSON_FIT_SSID_H -#define LDSCTRLEST_LDS_POISSON_FIT_SSID_H - -#include "lds_fit_ssid.h" -#include "lds_poisson_fit.h" - -namespace lds { -namespace poisson { -class FitSSID : public SSID { - public: - using SSID::SSID; - - private: - void DecomposeData() override; - - void CalcCov(); - - void PoissonToGaussianMoments(); - Matrix cov_; -}; - -} // namespace poisson -} // namespace lds -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_poisson_fit_ssid.h +summary: PLDS SSID fit type. + +--- + +# ldsCtrlEst_h/lds_poisson_fit_ssid.h + +PLDS SSID fit type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::poisson::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_fit_s_s_i_d/)**
Subspace Identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1_s_s_i_d/)) for PLDS. | + +## Detailed Description + + + +This file declares and partially defines a type by which Poisson-output LDS models are fit by a subspace identification (SSID) algorithm (`[lds::gaussian::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit_s_s_i_d/)`). + +References: [1] van Overschee P, de Moore B. (1996) Subspace Identification for Linear Systems. Boston: Springer. [2] Buesing L, Macke JH, Sahani M. (2012) Spectral learning of linear dynamics from generalised-linear observations with application to neural population data. NIPS 25. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_poisson_fit_ssid.h - PLDS Fit (SSID) ---*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_POISSON_FIT_SSID_H +#define LDSCTRLEST_LDS_POISSON_FIT_SSID_H + +#include "lds_fit_ssid.h" +#include "lds_poisson_fit.h" + +namespace lds { +namespace poisson { +class FitSSID : public SSID { + public: + using SSID::SSID; + + private: + void DecomposeData() override; + + void CalcCov(); + + void PoissonToGaussianMoments(); + Matrix cov_; +}; + +} // namespace poisson +} // namespace lds +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__poisson__sctrl_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__poisson__sctrl_8h.md index 885a2585..391d5734 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__poisson__sctrl_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__poisson__sctrl_8h.md @@ -1,117 +1,117 @@ ---- -title: ldsCtrlEst_h/lds_poisson_sctrl.h -summary: PLDS switched controller type. - ---- - -# ldsCtrlEst_h/lds_poisson_sctrl.h - -PLDS switched controller type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::poisson::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1switchedcontroller/)**
Poisson-observation [SwitchedController]() Type. | - -## Detailed Description - - - -This file declares and partially defines the type for switched feedback control of a system approximated as multiple discrete Poisson-output linear dynamical systems ([lds::poisson::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1switchedcontroller/)). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_poisson_sctrl.h - Switched Controller --*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_POISSON_SWITCHED_CTRL_H -#define LDSCTRLEST_LDS_POISSON_SWITCHED_CTRL_H - -#include "lds_poisson_ctrl.h" -#include "lds_sctrl.h" - -namespace lds { -namespace poisson { -class SwitchedController : public lds::SwitchedController { - public: - void set_y_ref(const Vector& y_ref) override { - Reassign(y_ref_,y_ref); - lds::Limit(y_ref_, kYRefLB, lds::kInf); - cx_ref_ = log(y_ref_) - sys_.d(); - }; - - // make sure base class template methods available - using lds::SwitchedController::SwitchedController; - using lds::SwitchedController::Switch; - using lds::SwitchedController::Control; - using lds::SwitchedController::ControlOutputReference; - - using lds::SwitchedController::sys; - using lds::SwitchedController::Kc; - using lds::SwitchedController::Kc_inty; - using lds::SwitchedController::Kc_u; - using lds::SwitchedController::g_design; - using lds::SwitchedController::u_ref; - using lds::SwitchedController::x_ref; - using lds::SwitchedController::y_ref; - using lds::SwitchedController::control_type; - - using lds::SwitchedController::set_g_design; - using lds::SwitchedController::set_u_ref; - using lds::SwitchedController::set_x_ref; - using lds::SwitchedController::set_y_ref; - using lds::SwitchedController::set_Kc; - using lds::SwitchedController::set_Kc_inty; - using lds::SwitchedController::set_Kc_u; - using lds::SwitchedController::set_tau_awu; - using lds::SwitchedController::set_control_type; - - using lds::SwitchedController::Reset; - using lds::SwitchedController::Print; - - private: - constexpr static data_t kYRefLB = - 1e-4; -}; -} // namespace poisson -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_poisson_sctrl.h +summary: PLDS switched controller type. + +--- + +# ldsCtrlEst_h/lds_poisson_sctrl.h + +PLDS switched controller type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::poisson::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_switched_controller/)**
Poisson-observation [SwitchedController]() Type. | + +## Detailed Description + + + +This file declares and partially defines the type for switched feedback control of a system approximated as multiple discrete Poisson-output linear dynamical systems ([lds::poisson::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_switched_controller/)). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_poisson_sctrl.h - Switched Controller --*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_POISSON_SWITCHED_CTRL_H +#define LDSCTRLEST_LDS_POISSON_SWITCHED_CTRL_H + +#include "lds_poisson_ctrl.h" +#include "lds_sctrl.h" + +namespace lds { +namespace poisson { +class SwitchedController : public lds::SwitchedController { + public: + void set_y_ref(const Vector& y_ref) override { + Reassign(y_ref_,y_ref); + lds::Limit(y_ref_, kYRefLB, lds::kInf); + cx_ref_ = log(y_ref_) - sys_.d(); + }; + + // make sure base class template methods available + using lds::SwitchedController::SwitchedController; + using lds::SwitchedController::Switch; + using lds::SwitchedController::Control; + using lds::SwitchedController::ControlOutputReference; + + using lds::SwitchedController::sys; + using lds::SwitchedController::Kc; + using lds::SwitchedController::Kc_inty; + using lds::SwitchedController::Kc_u; + using lds::SwitchedController::g_design; + using lds::SwitchedController::u_ref; + using lds::SwitchedController::x_ref; + using lds::SwitchedController::y_ref; + using lds::SwitchedController::control_type; + + using lds::SwitchedController::set_g_design; + using lds::SwitchedController::set_u_ref; + using lds::SwitchedController::set_x_ref; + using lds::SwitchedController::set_y_ref; + using lds::SwitchedController::set_Kc; + using lds::SwitchedController::set_Kc_inty; + using lds::SwitchedController::set_Kc_u; + using lds::SwitchedController::set_tau_awu; + using lds::SwitchedController::set_control_type; + + using lds::SwitchedController::Reset; + using lds::SwitchedController::Print; + + private: + constexpr static data_t kYRefLB = + 1e-4; +}; +} // namespace poisson +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__poisson__sys_8cpp.md b/misc/docs-hugo/content/docs/api/Files/lds__poisson__sys_8cpp.md index 5981e03e..bc05a62d 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__poisson__sys_8cpp.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__poisson__sys_8cpp.md @@ -1,94 +1,94 @@ ---- -title: src/lds_poisson_sys.cpp -summary: PLDS base type. - ---- - -# src/lds_poisson_sys.cpp - -PLDS base type. [More...](#detailed-description) - - - -## Detailed Description - - - -This file implements the type for state estimation (filtering) as well as simulation of Poisson-output linear dynamical systems (`lds::poisson::sys_t`). It inherits functionality from the underlying linear dynamical system (`lds::sys_t`). - - - - - -## Source code - -```cpp -//===-- lds_poisson_sys.cpp - PLDS ----------------------------------------===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#include - -lds::poisson::System::System(size_t n_u, size_t n_x, size_t n_y, data_t dt, - data_t p0, data_t q0) - : lds::System(n_u, n_x, n_y, dt, p0, q0) { - diag_y_ = diagmat(y_); - pd_ = std::poisson_distribution(0); -}; - -// Correct: Given measurement (z) and current input (u), update estimate of the -// state, covar, output. -// -// see Eden et al. 2004 -void lds::poisson::System::RecurseKe() { - // predict covariance - P_ = A_ * P_ * A_.t() + Q_; - - // update cov - P_ = pinv(pinv(P_) + C_.t() * diag_y_ * C_); - Ke_ = P_ * C_.t(); - if (do_adapt_m) { - P_m_ += Q_m_; // predict (A_m = I) - P_m_ = pinv(pinv(P_m_) + C_.t() * diag_y_ * C_); // update - Ke_m_ = P_m_ * C_.t(); - } -} - -// Simulate Measurement: z ~ Poisson(y) -const lds::Vector& lds::poisson::System::Simulate(const Vector& u_tm1) { - f(u_tm1, true); // simulate dynamics with noise added - h(); // output - - z_.zeros(); - for (std::size_t k = 0; k < n_y_; k++) { - // construct a Poisson distribution object with mean y[k] - pd_ = std::poisson_distribution(y_[k]); - // pull random sample from this distribution - z_[k] = pd_(rng); - } - - return z_; -} -// ******************* SYS_T ******************* -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: src/lds_poisson_sys.cpp +summary: PLDS base type. + +--- + +# src/lds_poisson_sys.cpp + +PLDS base type. [More...](#detailed-description) + + + +## Detailed Description + + + +This file implements the type for state estimation (filtering) as well as simulation of Poisson-output linear dynamical systems (`lds::poisson::sys_t`). It inherits functionality from the underlying linear dynamical system (`lds::sys_t`). + + + + + +## Source code + +```cpp +//===-- lds_poisson_sys.cpp - PLDS ----------------------------------------===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#include + +lds::poisson::System::System(size_t n_u, size_t n_x, size_t n_y, data_t dt, + data_t p0, data_t q0) + : lds::System(n_u, n_x, n_y, dt, p0, q0) { + diag_y_ = diagmat(y_); + pd_ = std::poisson_distribution(0); +}; + +// Correct: Given measurement (z) and current input (u), update estimate of the +// state, covar, output. +// +// see Eden et al. 2004 +void lds::poisson::System::RecurseKe() { + // predict covariance + P_ = A_ * P_ * A_.t() + Q_; + + // update cov + P_ = pinv(pinv(P_) + C_.t() * diag_y_ * C_); + Ke_ = P_ * C_.t(); + if (do_adapt_m) { + P_m_ += Q_m_; // predict (A_m = I) + P_m_ = pinv(pinv(P_m_) + C_.t() * diag_y_ * C_); // update + Ke_m_ = P_m_ * C_.t(); + } +} + +// Simulate Measurement: z ~ Poisson(y) +const lds::Vector& lds::poisson::System::Simulate(const Vector& u_tm1) { + f(u_tm1, true); // simulate dynamics with noise added + h(); // output + + z_.zeros(); + for (std::size_t k = 0; k < n_y_; k++) { + // construct a Poisson distribution object with mean y[k] + pd_ = std::poisson_distribution(y_[k]); + // pull random sample from this distribution + z_[k] = pd_(rng); + } + + return z_; +} +// ******************* SYS_T ******************* +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__poisson__sys_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__poisson__sys_8h.md index 4dbed5d6..e56ada16 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__poisson__sys_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__poisson__sys_8h.md @@ -1,106 +1,108 @@ ---- -title: ldsCtrlEst_h/lds_poisson_sys.h -summary: PLDS base type. - ---- - -# ldsCtrlEst_h/lds_poisson_sys.h - -PLDS base type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | -| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::poisson::System](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1system/)**
Poisson [System]() type. | - -## Detailed Description - - - -This file declares and partially defines the type for state estimation (filtering) as well as simulation of Poisson-output linear dynamical systems (`[lds::poisson::System](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1system/)`). It inherits functionality from the underlying linear dynamical system (`[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1system/)`). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_poisson_sys.h - PLDS -------------------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_POISSON_SYS_H -#define LDSCTRLEST_LDS_POISSON_SYS_H - -// namespace -#include "lds_poisson.h" -// system -#include "lds_sys.h" - -// needed for Poisson random number generation -#include - -namespace lds { -namespace poisson { - -class System : public lds::System { - public: - System() = default; - - System(std::size_t n_u, std::size_t n_x, std::size_t n_y, data_t dt, - data_t p0 = kDefaultP0, data_t q0 = kDefaultQ0); - - const Vector& Simulate(const Vector& u_tm1) override; - - protected: - void h() override { - cx_ = C_ * x_; - y_ = exp(cx_ + d_); - diag_y_.diag() = y_; - }; - - void RecurseKe() override; - - private: - // Poisson-output-specific - Matrix diag_y_; - std::poisson_distribution - pd_; -}; // System -} // namespace poisson -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_poisson_sys.h +summary: PLDS base type. + +--- + +# ldsCtrlEst_h/lds_poisson_sys.h + +PLDS base type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | +| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::poisson::System](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_system/)**
Poisson [System]() type. | + +## Detailed Description + + + +This file declares and partially defines the type for state estimation (filtering) as well as simulation of Poisson-output linear dynamical systems (`[lds::poisson::System](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_system/)`). It inherits functionality from the underlying linear dynamical system (`[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1_system/)`). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_poisson_sys.h - PLDS -------------------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_POISSON_SYS_H +#define LDSCTRLEST_LDS_POISSON_SYS_H + +// namespace +#include "lds_poisson.h" +// system +#include "lds_sys.h" + +// needed for Poisson random number generation +#include + +namespace lds { +namespace poisson { + +class System : public lds::System { + public: + System() = default; + + System(std::size_t n_u, std::size_t n_x, std::size_t n_y, data_t dt, + data_t p0 = kDefaultP0, data_t q0 = kDefaultQ0); + + const Vector& Simulate(const Vector& u_tm1) override; + + protected: + void h() override { + cx_ = C_ * x_; + y_ = exp(cx_ + d_); + diag_y_.diag() = y_; + }; + + Vector h_(Vector x) override { return exp(C_ * x + d_); }; + + void RecurseKe() override; + + private: + // Poisson-output-specific + Matrix diag_y_; + std::poisson_distribution + pd_; +}; // System +} // namespace poisson +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__sctrl_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__sctrl_8h.md index c59f532d..46272b6d 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__sctrl_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__sctrl_8h.md @@ -1,275 +1,275 @@ ---- -title: ldsCtrlEst_h/lds_sctrl.h -summary: SwitchedController type. - ---- - -# ldsCtrlEst_h/lds_sctrl.h - -SwitchedController type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1switchedcontroller/)**
[SwitchedController]() Type. | - -## Detailed Description - - - -This file declares the type for switched control of a system approximated as multiple discrete Gaussian-output linear dynamical systems ([lds::gaussian::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1switchedcontroller/)). - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_sctrl.h - Switched Controller ----------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_SCTRL_H -#define LDSCTRLEST_LDS_SCTRL_H - -#include "lds_ctrl.h" -#include "lds_uniform_mats.h" -#include "lds_uniform_vecs.h" - -namespace lds { -template -class SwitchedController : public Controller { - public: - SwitchedController() = default; - - SwitchedController(const std::vector& systems, data_t u_lb, - data_t u_ub, size_t control_type = 0); - - SwitchedController(std::vector&& systems, data_t u_lb, data_t u_ub, - size_t control_type = 0); - - void Switch(size_t idx, bool do_force_switch = false); - - void set_Kc(const UniformMatrixList<>& Kc) { - Kc_list_ = Kc; - Kc_ = Kc_list_.at(0); // set to first - if (idx_ != 0) { - Switch(idx_, true); - } - }; - void set_Kc(UniformMatrixList<>&& Kc) { - Kc_list_ = std::move(Kc); - Kc_ = Kc_list_.at(0); // set to first - if (idx_ != 0) { - Switch(idx_, true); - } - }; - - void set_Kc_inty(const UniformMatrixList<>& Kc_inty) { - Kc_inty_list_ = Kc_inty; - Kc_inty_ = Kc_inty_list_.at(0); // set to first - if (idx_ != 0) { - Switch(idx_, true); - } - }; - void set_Kc_inty(UniformMatrixList<>&& Kc_inty) { - Kc_inty_list_ = std::move(Kc_inty); - Kc_inty_ = Kc_inty_list_.at(0); // set to first - if (idx_ != 0) { - Switch(idx_, true); - } - }; - - void set_Kc_u(const UniformMatrixList<>& Kc_u) { - Kc_u_list_ = Kc_u; - Kc_u_ = Kc_u_list_.at(0); // set to first - if (idx_ != 0) { - Switch(idx_, true); - } - }; - void set_Kc_u(UniformMatrixList<>&& Kc_u) { - Kc_u_list_ = std::move(Kc_u); - Kc_u_ = Kc_u_list_.at(0); // set to first - if (idx_ != 0) { - Switch(idx_, true); - } - }; - - void set_g_design(const UniformVectorList& g) { - g_design_list_ = g; - g_design_ = g_design_list_.at(0); // set to first - if (idx_ != 0) { - Switch(idx_, true); - } - }; - void set_g_design(UniformVectorList&& g) { - g_design_list_ = std::move(g); - g_design_ = g_design_list_.at(0); // set to first - if (idx_ != 0) { - Switch(idx_, true); - } - }; - - // make sure base class template methods available - using lds::Controller::Controller; - using lds::Controller::Control; - using lds::Controller::ControlOutputReference; - - using lds::Controller::sys; - using lds::Controller::Kc; - using lds::Controller::Kc_inty; - using lds::Controller::Kc_u; - using lds::Controller::g_design; - using lds::Controller::u_ref; - using lds::Controller::x_ref; - using lds::Controller::y_ref; - using lds::Controller::control_type; - - using lds::Controller::set_u_ref; - using lds::Controller::set_x_ref; - using lds::Controller::set_y_ref; - using lds::Controller::set_tau_awu; - using lds::Controller::set_control_type; - - using lds::Controller::Reset; - using lds::Controller::Print; - - protected: - std::vector - systems_; - size_t n_sys_{}; - size_t idx_{}; - - // controller gains could be different for each - UniformMatrixList<> Kc_list_; - UniformMatrixList<> Kc_inty_list_; - UniformMatrixList<> Kc_u_list_; - - // design-phase input gain could also be different - UniformVectorList g_design_list_; - - // TODO(mfbolus): not sure why I need to do this. - using Controller::Kc_; - using Controller::Kc_inty_; - using Controller::Kc_u_; - using Controller::g_design_; - using Controller::sys_; - // using Controller::u_ref_; - // using Controller::x_ref_; - // using Controller::y_ref_; - // - using Controller::control_type_; - - private: - void InitVars(); - - using lds::Controller::set_sys; - // using Controller::set_Kc; - // using Controller::set_Kc_inty; - // using Controller::set_Kc_u; - // using Controller::set_g_design; -}; - -template -inline SwitchedController::SwitchedController( - const std::vector& systems, data_t u_lb, data_t u_ub, - size_t control_type) - : Controller(systems.at(0), u_lb, u_ub, control_type), - systems_(systems) { - InitVars(); -} - -template -inline SwitchedController::SwitchedController( - std::vector&& systems, data_t u_lb, data_t u_ub, - size_t control_type) - : Controller(System(systems.at(0).n_u(), systems.at(0).n_x(), - systems.at(0).n_y(), systems.at(0).dt()), - u_lb, u_ub, control_type), - systems_(std::move(systems)) { - InitVars(); -} - -template -inline void SwitchedController::InitVars() { - n_sys_ = systems_.size(); - sys_ = systems_.at(0); - - Kc_list_ = UniformMatrixList<>(std::vector(n_sys_, Kc_)); - Kc_inty_list_ = UniformMatrixList<>(std::vector(n_sys_, Kc_inty_)); - Kc_u_list_ = UniformMatrixList<>(std::vector(n_sys_, Kc_inty_)); - g_design_list_ = UniformVectorList(std::vector(n_sys_, g_design_)); -} - -template -inline void SwitchedController::Switch(size_t idx, - bool do_force_switch) { - if ((idx == idx_) && !do_force_switch) { - return; // already there. - } - - // put old up and get new one out - systems_.at(idx_) = std::move(sys_); - sys_ = std::move(systems_.at(idx)); - - // set the state of this system to that of the previous system - // TODO(mfbolus): This will only work as intended if state matrix is the same. - // See example fudge in 0.4 branch src/lds_poisson_sctrl.cpp. - sys_.set_m(systems_.at(idx_).m(), true); - sys_.set_x(systems_.at(idx_).x()); - - // swap controller gains - Kc_list_.Swap(Kc_, idx_); - Kc_list_.Swap(Kc_, idx); - - if (control_type_ & kControlTypeIntY) { - Kc_inty_list_.Swap(Kc_inty_, idx_); - Kc_inty_list_.Swap(Kc_inty_, idx); - } - - if (control_type_ & kControlTypeDeltaU) { - Kc_u_list_.Swap(Kc_u_, idx_); - Kc_u_list_.Swap(Kc_u_, idx); - } - - g_design_list_.Swap(g_design_, idx_); - g_design_list_.Swap(g_design_, idx); - - idx_ = idx; -} // Switch - -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_sctrl.h +summary: SwitchedController type. + +--- + +# ldsCtrlEst_h/lds_sctrl.h + +SwitchedController type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1_switched_controller/)**
[SwitchedController]() Type. | + +## Detailed Description + + + +This file declares the type for switched control of a system approximated as multiple discrete Gaussian-output linear dynamical systems ([lds::gaussian::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_switched_controller/)). + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_sctrl.h - Switched Controller ----------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_SCTRL_H +#define LDSCTRLEST_LDS_SCTRL_H + +#include "lds_ctrl.h" +#include "lds_uniform_mats.h" +#include "lds_uniform_vecs.h" + +namespace lds { +template +class SwitchedController : public Controller { + public: + SwitchedController() = default; + + SwitchedController(const std::vector& systems, data_t u_lb, + data_t u_ub, size_t control_type = 0); + + SwitchedController(std::vector&& systems, data_t u_lb, data_t u_ub, + size_t control_type = 0); + + void Switch(size_t idx, bool do_force_switch = false); + + void set_Kc(const UniformMatrixList<>& Kc) { + Kc_list_ = Kc; + Kc_ = Kc_list_.at(0); // set to first + if (idx_ != 0) { + Switch(idx_, true); + } + }; + void set_Kc(UniformMatrixList<>&& Kc) { + Kc_list_ = std::move(Kc); + Kc_ = Kc_list_.at(0); // set to first + if (idx_ != 0) { + Switch(idx_, true); + } + }; + + void set_Kc_inty(const UniformMatrixList<>& Kc_inty) { + Kc_inty_list_ = Kc_inty; + Kc_inty_ = Kc_inty_list_.at(0); // set to first + if (idx_ != 0) { + Switch(idx_, true); + } + }; + void set_Kc_inty(UniformMatrixList<>&& Kc_inty) { + Kc_inty_list_ = std::move(Kc_inty); + Kc_inty_ = Kc_inty_list_.at(0); // set to first + if (idx_ != 0) { + Switch(idx_, true); + } + }; + + void set_Kc_u(const UniformMatrixList<>& Kc_u) { + Kc_u_list_ = Kc_u; + Kc_u_ = Kc_u_list_.at(0); // set to first + if (idx_ != 0) { + Switch(idx_, true); + } + }; + void set_Kc_u(UniformMatrixList<>&& Kc_u) { + Kc_u_list_ = std::move(Kc_u); + Kc_u_ = Kc_u_list_.at(0); // set to first + if (idx_ != 0) { + Switch(idx_, true); + } + }; + + void set_g_design(const UniformVectorList& g) { + g_design_list_ = g; + g_design_ = g_design_list_.at(0); // set to first + if (idx_ != 0) { + Switch(idx_, true); + } + }; + void set_g_design(UniformVectorList&& g) { + g_design_list_ = std::move(g); + g_design_ = g_design_list_.at(0); // set to first + if (idx_ != 0) { + Switch(idx_, true); + } + }; + + // make sure base class template methods available + using lds::Controller::Controller; + using lds::Controller::Control; + using lds::Controller::ControlOutputReference; + + using lds::Controller::sys; + using lds::Controller::Kc; + using lds::Controller::Kc_inty; + using lds::Controller::Kc_u; + using lds::Controller::g_design; + using lds::Controller::u_ref; + using lds::Controller::x_ref; + using lds::Controller::y_ref; + using lds::Controller::control_type; + + using lds::Controller::set_u_ref; + using lds::Controller::set_x_ref; + using lds::Controller::set_y_ref; + using lds::Controller::set_tau_awu; + using lds::Controller::set_control_type; + + using lds::Controller::Reset; + using lds::Controller::Print; + + protected: + std::vector + systems_; + size_t n_sys_{}; + size_t idx_{}; + + // controller gains could be different for each + UniformMatrixList<> Kc_list_; + UniformMatrixList<> Kc_inty_list_; + UniformMatrixList<> Kc_u_list_; + + // design-phase input gain could also be different + UniformVectorList g_design_list_; + + // TODO(mfbolus): not sure why I need to do this. + using Controller::Kc_; + using Controller::Kc_inty_; + using Controller::Kc_u_; + using Controller::g_design_; + using Controller::sys_; + // using Controller::u_ref_; + // using Controller::x_ref_; + // using Controller::y_ref_; + // + using Controller::control_type_; + + private: + void InitVars(); + + using lds::Controller::set_sys; + // using Controller::set_Kc; + // using Controller::set_Kc_inty; + // using Controller::set_Kc_u; + // using Controller::set_g_design; +}; + +template +inline SwitchedController::SwitchedController( + const std::vector& systems, data_t u_lb, data_t u_ub, + size_t control_type) + : Controller(systems.at(0), u_lb, u_ub, control_type), + systems_(systems) { + InitVars(); +} + +template +inline SwitchedController::SwitchedController( + std::vector&& systems, data_t u_lb, data_t u_ub, + size_t control_type) + : Controller(System(systems.at(0).n_u(), systems.at(0).n_x(), + systems.at(0).n_y(), systems.at(0).dt()), + u_lb, u_ub, control_type), + systems_(std::move(systems)) { + InitVars(); +} + +template +inline void SwitchedController::InitVars() { + n_sys_ = systems_.size(); + sys_ = systems_.at(0); + + Kc_list_ = UniformMatrixList<>(std::vector(n_sys_, Kc_)); + Kc_inty_list_ = UniformMatrixList<>(std::vector(n_sys_, Kc_inty_)); + Kc_u_list_ = UniformMatrixList<>(std::vector(n_sys_, Kc_inty_)); + g_design_list_ = UniformVectorList(std::vector(n_sys_, g_design_)); +} + +template +inline void SwitchedController::Switch(size_t idx, + bool do_force_switch) { + if ((idx == idx_) && !do_force_switch) { + return; // already there. + } + + // put old up and get new one out + systems_.at(idx_) = std::move(sys_); + sys_ = std::move(systems_.at(idx)); + + // set the state of this system to that of the previous system + // TODO(mfbolus): This will only work as intended if state matrix is the same. + // See example fudge in 0.4 branch src/lds_poisson_sctrl.cpp. + sys_.set_m(systems_.at(idx_).m(), true); + sys_.set_x(systems_.at(idx_).x()); + + // swap controller gains + Kc_list_.Swap(Kc_, idx_); + Kc_list_.Swap(Kc_, idx); + + if (control_type_ & kControlTypeIntY) { + Kc_inty_list_.Swap(Kc_inty_, idx_); + Kc_inty_list_.Swap(Kc_inty_, idx); + } + + if (control_type_ & kControlTypeDeltaU) { + Kc_u_list_.Swap(Kc_u_, idx_); + Kc_u_list_.Swap(Kc_u_, idx); + } + + g_design_list_.Swap(g_design_, idx_); + g_design_list_.Swap(g_design_, idx); + + idx_ = idx; +} // Switch + +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__sys_8cpp.md b/misc/docs-hugo/content/docs/api/Files/lds__sys_8cpp.md index 8e313360..1fec9cae 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__sys_8cpp.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__sys_8cpp.md @@ -1,140 +1,184 @@ ---- -title: src/lds_sys.cpp -summary: LDS base type. - ---- - -# src/lds_sys.cpp - -LDS base type. [More...](#detailed-description) - - - -## Detailed Description - - - -This file implements the base type for linear dynamical systems ([lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1system/)). Note that this class defines the underlying linear dynamics, but does not have output functions.Gaussian- and Poisson-output variants will be built upon this class. - - - - - -## Source code - -```cpp -//===-- lds_sys.cpp - LDS -------------------------------------------------===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#include - -lds::System::System(size_t n_u, size_t n_x, size_t n_y, data_t dt, data_t p0, - data_t q0) - : n_u_(n_u), n_x_(n_x), n_y_(n_y), dt_(dt) { - InitVars(p0, q0); -} - -void lds::System::InitVars(data_t p0, data_t q0) { - // initial conditions. - x0_ = Vector(n_x_, fill::zeros); // includes bias (nY) and g (nU) - P0_ = p0 * Matrix(n_x_, n_x_, fill::eye); - - m0_ = x0_; - P0_m_ = P0_; - - // signals - x_ = x0_; - P_ = P0_; - m_ = m0_; - P_m_ = P0_m_; - y_ = Vector(n_y_, fill::zeros); - cx_ = Vector(n_y_, fill::zeros); - z_ = Vector(n_y_, fill::zeros); - - // By default, random walk where each state is independent - // In this way, provides independent estimates of rate per channel of output. - A_ = Matrix(n_x_, n_x_, fill::eye); - B_ = Matrix(n_x_, n_u_, fill::zeros); - g_ = Vector(n_u_, fill::ones); - Q_ = q0 * Matrix(n_x_, n_x_, fill::eye); - Q_m_ = Q_; - - C_ = Matrix(n_y_, n_x_, fill::eye); // each state will map to an output by - d_ = Vector(n_y_, fill::zeros); - - Ke_ = Matrix(n_x_, n_y_, fill::zeros); // estimator gain. - Ke_m_ = Matrix(n_x_, n_y_, fill::zeros); // estimator gain for m adaptation. - - do_adapt_m = false; -} - -// Filter: Given measurement (`z`) and previous input (`u_tm1`), predict state -// and update estimate of the state, covar, output using Kalman filter -void lds::System::Filter(const Vector& u_tm1, const Vector& z_t) { - // predict mean - f(u_tm1); // dynamics - - h(); // output - - // recursively calculate esimator gains (or just keep existing values) - // (also predicts+updates estimate covariance) - RecurseKe(); - - // update - x_ += Ke_ * (z_t - y_); - if (do_adapt_m) { - m_ += Ke_m_ * (z_t - y_); // adaptively estimating disturbance - } - - // With new state, estimate output. - h(); // --> posterior -} - -void lds::System::Reset() { - // reset to initial conditions - x_ = x0_; // mean - P_ = P0_; // cov of state estimate - m_ = m0_; // process disturbance - P_m_ = P0_m_; // cov of disturbance estimate - h(); -} - -void lds::System::Print() { - std::cout << "\n ********** SYSTEM ********** \n"; - std::cout << "x: \n" << x_ << "\n"; - std::cout << "P: \n" << P_ << "\n"; - std::cout << "A: \n" << A_ << "\n"; - std::cout << "B: \n" << B_ << "\n"; - std::cout << "g: \n" << g_ << "\n"; - std::cout << "m: \n" << m_ << "\n"; - std::cout << "Q: \n" << Q_ << "\n"; - std::cout << "Q_m: \n" << Q_m_ << "\n"; - std::cout << "d: \n" << d_ << "\n"; - std::cout << "C: \n" << C_ << "\n"; - std::cout << "y: \n" << y_ << "\n"; -} - -//******************* SYS_T ******************* -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: src/lds_sys.cpp +summary: LDS base type. + +--- + +# src/lds_sys.cpp + +LDS base type. [More...](#detailed-description) + + + +## Detailed Description + + + +This file implements the base type for linear dynamical systems ([lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1_system/)). Note that this class defines the underlying linear dynamics, but does not have output functions.Gaussian- and Poisson-output variants will be built upon this class. + + + + + +## Source code + +```cpp +//===-- lds_sys.cpp - LDS -------------------------------------------------===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#include + +#include + +lds::System::System(size_t n_u, size_t n_x, size_t n_y, data_t dt, data_t p0, + data_t q0) + : n_u_(n_u), n_x_(n_x), n_y_(n_y), dt_(dt) { + InitVars(p0, q0); +} + +void lds::System::InitVars(data_t p0, data_t q0) { + // initial conditions. + x0_ = Vector(n_x_, fill::zeros); // includes bias (nY) and g (nU) + P0_ = p0 * Matrix(n_x_, n_x_, fill::eye); + + m0_ = x0_; + P0_m_ = P0_; + + // signals + x_ = x0_; + P_ = P0_; + m_ = m0_; + P_m_ = P0_m_; + y_ = Vector(n_y_, fill::zeros); + cx_ = Vector(n_y_, fill::zeros); + z_ = Vector(n_y_, fill::zeros); + + // By default, random walk where each state is independent + // In this way, provides independent estimates of rate per channel of output. + A_ = Matrix(n_x_, n_x_, fill::eye); + B_ = Matrix(n_x_, n_u_, fill::zeros); + g_ = Vector(n_u_, fill::ones); + Q_ = q0 * Matrix(n_x_, n_x_, fill::eye); + Q_m_ = Q_; + + C_ = Matrix(n_y_, n_x_, fill::eye); // each state will map to an output by + d_ = Vector(n_y_, fill::zeros); + + Ke_ = Matrix(n_x_, n_y_, fill::zeros); // estimator gain. + Ke_m_ = Matrix(n_x_, n_y_, fill::zeros); // estimator gain for m adaptation. + + do_adapt_m = false; +} + +// Filter: Given measurement (`z`) and previous input (`u_tm1`), predict state +// and update estimate of the state, covar, output using Kalman filter +void lds::System::Filter(const Vector& u_tm1, const Vector& z_t) { + // predict mean + f(u_tm1); // dynamics + + h(); // output + + // recursively calculate esimator gains (or just keep existing values) + // (also predicts+updates estimate covariance) + RecurseKe(); + + // update + x_ += Ke_ * (z_t - y_); + if (do_adapt_m) { + m_ += Ke_m_ * (z_t - y_); // adaptively estimating disturbance + } + + // With new state, estimate output. + h(); // --> posterior +} + +void lds::System::Reset() { + // reset to initial conditions + x_ = x0_; // mean + P_ = P0_; // cov of state estimate + m_ = m0_; // process disturbance + P_m_ = P0_m_; // cov of disturbance estimate + h(); +} + +std::vector> +lds::System::nstep_pred_block(lds::UniformMatrixList u, + lds::UniformMatrixList z, + size_t n_pred) { + lds::UniformMatrixList x_filt; + lds::UniformMatrixList x_pred; + lds::UniformMatrixList y_pred; + + for (size_t k = 0; k < u.size(); k++) { + Reset(); + size_t n_t = arma::size(u[k])[1]; + Matrix x_filt_k(n_x_, n_t, fill::zeros); + Matrix x_pred_k(n_x_, n_t - n_pred, fill::zeros); + Matrix y_pred_k(n_y_, n_t - n_pred, fill::zeros); + + for (size_t t = 0; t < n_t - n_pred; t++) { + Vector x_pred_ahead = x_; + for (size_t t_u = t; t_u < t + n_pred; t_u++) { + x_pred_ahead = A_ * x_pred_ahead + B_ * u[k].col(t_u); + } + x_pred_k.col(t) = x_pred_ahead; + y_pred_k.col(t) = h_(x_pred_ahead); + if (t > 0) { + Filter(u[k].col(t - 1), z[k].col(t)); + } + x_filt_k.col(t) = x_; // given previous measurment + } + + for (size_t t = n_t - n_pred; t < n_t; t++) { + if (t > 0) { + Filter(u[k].col(t - 1), z[k].col(t)); + } + x_filt_k.col(t) = x_; + } + + x_filt.append(x_filt_k); + x_pred.append(x_pred_k); + y_pred.append(y_pred_k); + } + return {x_filt, x_pred, y_pred}; +} + +void lds::System::Print() { + std::cout << "\n ********** SYSTEM ********** \n"; + std::cout << "x: \n" << x_ << "\n"; + std::cout << "P: \n" << P_ << "\n"; + std::cout << "A: \n" << A_ << "\n"; + std::cout << "B: \n" << B_ << "\n"; + std::cout << "g: \n" << g_ << "\n"; + std::cout << "m: \n" << m_ << "\n"; + std::cout << "Q: \n" << Q_ << "\n"; + std::cout << "Q_m: \n" << Q_m_ << "\n"; + std::cout << "d: \n" << d_ << "\n"; + std::cout << "C: \n" << C_ << "\n"; + std::cout << "y: \n" << y_ << "\n"; +} + +//******************* SYS_T ******************* +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__sys_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__sys_8h.md index 9e9688d3..a1662298 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__sys_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__sys_8h.md @@ -1,184 +1,191 @@ ---- -title: ldsCtrlEst_h/lds_sys.h -summary: LDS base type. - ---- - -# ldsCtrlEst_h/lds_sys.h - -LDS base type. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1system/)**
Linear Dynamical [System]() Type. | - -## Detailed Description - - - -This file declares and partially defines the base type for linear dynamical systems (`[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1system/)`). Note that this class defines the underlying linear dynamics, but does not have output functions.Gaussian- and Poisson-output variants will be built upon this class. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_sys.h - LDS ----------------------------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// Limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_SYS_H -#define LDSCTRLEST_LDS_SYS_H - -#include "lds.h" - -namespace lds { -class System { - public: - System() = default; - - System(size_t n_u, size_t n_x, size_t n_y, data_t dt, data_t p0 = kDefaultP0, - data_t q0 = kDefaultQ0); - - virtual ~System() {} - - void Filter(const Vector& u_tm1, const Vector& z); - - virtual const Vector& Simulate(const Vector& u_tm1) = 0; - - void f(const Vector& u, bool do_add_noise = false) { - x_ = A_ * x_ + B_ * (g_ % u) + m_; - if (do_add_noise) { - x_ += arma::mvnrnd(Vector(n_x_).fill(0), Q_); - } - }; - - virtual void h() = 0; - - size_t n_u() const { return n_u_; }; - size_t n_x() const { return n_x_; }; - size_t n_y() const { return n_y_; }; - data_t dt() const { return dt_; }; - - const Vector& x() const { return x_; }; - const Matrix& P() const { return P_; }; - const Vector& m() const { return m_; }; - const Matrix& P_m() const { return P_m_; }; - const Vector& cx() const { return cx_; }; - const Vector& y() const { return y_; }; - - const Vector& x0() const { return x0_; }; - const Vector& m0() const { return m0_; }; - - const Matrix& A() const { return A_; }; - const Matrix& B() const { return B_; }; - const Vector& g() const { return g_; }; - const Matrix& C() const { return C_; }; - const Vector& d() const { return d_; }; - const Matrix& Ke() const { return Ke_; }; - const Matrix& Ke_m() const { return Ke_m_; }; - const Matrix& Q() { return Q_; }; - const Matrix& Q_m() { return Q_m_; }; - const Matrix& P0() { return P0_; }; - const Matrix& P0_m() { return P0_m_; }; - - void set_A(const Matrix& A) { Reassign(A_, A); }; - void set_B(const Matrix& B) { Reassign(B_, B); }; - void set_m(const Vector& m, bool do_force_assign=false) { - Reassign(m0_, m); - if ((!do_adapt_m) || do_force_assign) { - Reassign(m_, m); - } - }; - void set_g(const Vector& g) { Reassign(g_, g); }; - void set_Q(const Matrix& Q) { Reassign(Q_, Q); }; - void set_Q_m(const Matrix& Q_m) { Reassign(Q_m_, Q_m); }; - void set_x0(const Vector& x0) { Reassign(x0_, x0); }; - void set_P0(const Matrix& P0) { Reassign(P0_, P0); }; - void set_P0_m(const Matrix& P0_m) { Reassign(P0_m_, P0_m); }; - void set_C(const Matrix& C) { Reassign(C_, C); }; - void set_d(const Vector& d) { Reassign(d_, d); }; - void set_x(const Vector& x) { - Reassign(x_, x); - h(); - }; - - void Reset(); - - void Print(); - - // safe to leave this public and non-const - bool do_adapt_m{}; - - protected: - virtual void RecurseKe() = 0; - void InitVars(data_t p0 = kDefaultP0, data_t q0 = kDefaultQ0); - - std::size_t n_x_{}; - std::size_t n_u_{}; - std::size_t n_y_{}; - data_t dt_{}; - - // Signals: - Vector x_; - Matrix P_; - Vector m_; - Matrix P_m_; - Vector cx_; - Vector y_; - Vector z_; - - // Parameters: - Vector x0_; - Matrix P0_; - Vector m0_; - Matrix P0_m_; - Matrix A_; - Matrix B_; - Vector g_; - Matrix Q_; - Matrix Q_m_; - Matrix C_; - Vector d_; - - Matrix Ke_; - Matrix Ke_m_; -}; // System - -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_sys.h +summary: LDS base type. + +--- + +# ldsCtrlEst_h/lds_sys.h + +LDS base type. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1_system/)**
Linear Dynamical [System]() Type. | + +## Detailed Description + + + +This file declares and partially defines the base type for linear dynamical systems (`[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1_system/)`). Note that this class defines the underlying linear dynamics, but does not have output functions.Gaussian- and Poisson-output variants will be built upon this class. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_sys.h - LDS ----------------------------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// Limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_SYS_H +#define LDSCTRLEST_LDS_SYS_H + +#include "lds.h" +#include "lds_uniform_mats.h" + +namespace lds { +class System { + public: + System() = default; + + System(size_t n_u, size_t n_x, size_t n_y, data_t dt, data_t p0 = kDefaultP0, + data_t q0 = kDefaultQ0); + + virtual ~System() {} + + void Filter(const Vector& u_tm1, const Vector& z); + + virtual const Vector& Simulate(const Vector& u_tm1) = 0; + + void f(const Vector& u, bool do_add_noise = false) { + x_ = A_ * x_ + B_ * (g_ % u) + m_; + if (do_add_noise) { + x_ += arma::mvnrnd(Vector(n_x_).fill(0), Q_); + } + }; + + virtual void h() = 0; + + virtual Vector h_(Vector x) = 0; + + size_t n_u() const { return n_u_; }; + size_t n_x() const { return n_x_; }; + size_t n_y() const { return n_y_; }; + data_t dt() const { return dt_; }; + + const Vector& x() const { return x_; }; + const Matrix& P() const { return P_; }; + const Vector& m() const { return m_; }; + const Matrix& P_m() const { return P_m_; }; + const Vector& cx() const { return cx_; }; + const Vector& y() const { return y_; }; + + const Vector& x0() const { return x0_; }; + const Vector& m0() const { return m0_; }; + + const Matrix& A() const { return A_; }; + const Matrix& B() const { return B_; }; + const Vector& g() const { return g_; }; + const Matrix& C() const { return C_; }; + const Vector& d() const { return d_; }; + const Matrix& Ke() const { return Ke_; }; + const Matrix& Ke_m() const { return Ke_m_; }; + const Matrix& Q() { return Q_; }; + const Matrix& Q_m() { return Q_m_; }; + const Matrix& P0() { return P0_; }; + const Matrix& P0_m() { return P0_m_; }; + + void set_A(const Matrix& A) { Reassign(A_, A); }; + void set_B(const Matrix& B) { Reassign(B_, B); }; + void set_m(const Vector& m, bool do_force_assign = false) { + Reassign(m0_, m); + if ((!do_adapt_m) || do_force_assign) { + Reassign(m_, m); + } + }; + void set_g(const Vector& g) { Reassign(g_, g); }; + void set_Q(const Matrix& Q) { Reassign(Q_, Q); }; + void set_Q_m(const Matrix& Q_m) { Reassign(Q_m_, Q_m); }; + void set_x0(const Vector& x0) { Reassign(x0_, x0); }; + void set_P0(const Matrix& P0) { Reassign(P0_, P0); }; + void set_P0_m(const Matrix& P0_m) { Reassign(P0_m_, P0_m); }; + void set_C(const Matrix& C) { Reassign(C_, C); }; + void set_d(const Vector& d) { Reassign(d_, d); }; + void set_x(const Vector& x) { + Reassign(x_, x); + h(); + }; + + void Reset(); + + std::vector> nstep_pred_block( + UniformMatrixList u, UniformMatrixList z, + size_t n_pred = 1); + + void Print(); + + // safe to leave this public and non-const + bool do_adapt_m{}; + + protected: + virtual void RecurseKe() = 0; + void InitVars(data_t p0 = kDefaultP0, data_t q0 = kDefaultQ0); + + std::size_t n_x_{}; + std::size_t n_u_{}; + std::size_t n_y_{}; + data_t dt_{}; + + // Signals: + Vector x_; + Matrix P_; + Vector m_; + Matrix P_m_; + Vector cx_; + Vector y_; + Vector z_; + + // Parameters: + Vector x0_; + Matrix P0_; + Vector m0_; + Matrix P0_m_; + Matrix A_; + Matrix B_; + Vector g_; + Matrix Q_; + Matrix Q_m_; + Matrix C_; + Vector d_; + + Matrix Ke_; + Matrix Ke_m_; +}; // System + +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__uniform__mats_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__uniform__mats_8h.md index fa447ebb..17a80423 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__uniform__mats_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__uniform__mats_8h.md @@ -1,330 +1,343 @@ ---- -title: ldsCtrlEst_h/lds_uniform_mats.h -summary: List of uniformly sized matrices. - ---- - -# ldsCtrlEst_h/lds_uniform_mats.h - -List of uniformly sized matrices. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::UniformMatrixList](/lds-ctrl-est/docs/api/classes/classlds_1_1uniformmatrixlist/)** | - -## Detailed Description - - - -This file provides a container for uniformly sized matrices. Users may specify one dimension to be free to vary in the list. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_uniform_mats.h - Uniform Matrices ------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// Limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_UNIFORM_MATS_H -#define LDSCTRLEST_LDS_UNIFORM_MATS_H - -#include // std::array -#include // std::vector - -#include "lds.h" - -namespace lds { -template -class UniformMatrixList : public std::vector { - private: - // TODO(mfbolus): would rather *uncomment* the below for sake of conversion - // using std::vector::vector; - using std::vector::operator=; - using std::vector::operator[]; - using std::vector::begin; - using std::vector::end; - using std::vector::size; - - public: - using std::vector::at; - UniformMatrixList() = default; - - explicit UniformMatrixList(const std::vector& mats, - std::array dim = {0, 0}); - - explicit UniformMatrixList(std::vector&& mats, - std::array dim = {0, 0}); - - UniformMatrixList(std::initializer_list mats, - std::array dim = {0, 0}); - - UniformMatrixList(const UniformMatrixList& that); - - UniformMatrixList(UniformMatrixList&& that) noexcept; - - ~UniformMatrixList() = default; - - const std::array& dim(size_t n = 0) const { return dim_.at(n); } - - size_t size() { return std::vector::size(); }; - - const Matrix& at(size_t n) { return std::vector::at(n); }; - - void Swap(Matrix& that, size_t n); - - UniformMatrixList& operator=(const UniformMatrixList& that); - UniformMatrixList& operator=(UniformMatrixList&& that) noexcept; - - private: - void CheckDimensions(std::array dim); - std::vector> dim_; -}; - -template -inline void UniformMatrixList::Swap(Matrix& that, size_t n) { - // make sure request in range - if (n >= this->size()) { - std::cerr - << "Requested UniformMatrixList element out of bounds. Skipping.\n"; - return; - } - // check dim - bool does_match = true; - if (!(D == kMatFreeDim1)) { - does_match = does_match && (dim_[0][0] == that.n_rows); - } - if (!(D == kMatFreeDim2)) { - does_match = does_match && (dim_[0][1] == that.n_cols); - } - if (!does_match) { - std::cerr << "Cannot swap a UniformMatrixList element for an element of " - "different size. Skipping.\n"; - return; - } - // if checks pass, perform swap - Matrix tmp = std::move((*this)[n]); - (*this)[n] = std::move(that); - that = std::move(tmp); - - if (D == kMatFreeDim1) { - this->dim_[n][0] = (*this)[n].n_rows; - } - if (D == kMatFreeDim2) { - this->dim_[n][1] = (*this)[n].n_cols; - } -} - -template -inline UniformMatrixList& UniformMatrixList::operator=( - const UniformMatrixList& that) { - // make sure dim_ vector is initialized - if (dim_.empty()) { - dim_ = std::vector>(that.size(), {0, 0}); - } - // check dimensions - if (!this->empty()) { - if (this->size() != that.size()) { - std::ostringstream ss; - ss << "cannot reassign " << this->size() << " matrices with " - << that.size() << " matrices"; - throw std::runtime_error(ss.str()); - } - - // if dimensions a not zero and do not match, skip move with error message. - bool dims_nonzero = true; - for (auto d : dim_) { - if (!(D == kMatFreeDim1) && d[0] < 1) { - dims_nonzero = false; - break; - } - if (!(D == kMatFreeDim2) && d[1] < 1) { - dims_nonzero = false; - break; - } - } - if (dims_nonzero) { - bool does_match = true; - if (!(D == kMatFreeDim1)) { - does_match = does_match && (dim_[0][0] == that.at(0).n_rows); - } - if (!(D == kMatFreeDim2)) { - does_match = does_match && (dim_[0][1] == that.at(0).n_cols); - } - if (!does_match) { - std::ostringstream ss; - ss << "cannot reassign matrices of size " << dim_[0][0] << "x" - << dim_[0][1] << " with matrices of size " << that.at(0).n_rows - << "x" << that.at(0).n_cols; - throw std::runtime_error(ss.str()); - } - } - } - - for (size_t k = 0; k < this->size(); k++) { - (*this)[k] = that[k]; - dim_[k] = that.dim(k); - } - - return (*this); -} - -template -inline UniformMatrixList& UniformMatrixList::operator=( - UniformMatrixList&& that) noexcept { - // // check dimensions - // // if empty, assume a default constructed object and safe to move - // if (!this->empty()) { - // if (this->size() != that.size()) { - // std::cerr << "Cannot reassign " << this->size() << " matrices with " - // << that.size() << " matrices. Skipping.\n"; - // return (*this); - // } - // - // // if dimensions a not zero and do not match, skip move with error - // message. bool dims_nonzero = true; for (auto d : dim_) { - // if (!(D == kMatFreeDim1) && (d[0] < 1)) { - // dims_nonzero = false; - // break; - // } - // if (!(D == kMatFreeDim2) && (d[1] < 1)) { - // dims_nonzero = false; - // break; - // } - // } - // - // if (dims_nonzero) { - // bool does_match = true; - // if (!(D == kMatFreeDim1)) { - // does_match = does_match && (dim_[0][0] == that.at(0).n_rows); - // } - // - // if (!(D == kMatFreeDim2)) { - // does_match = does_match && (dim_[0][1] == that.at(0).n_cols); - // } - // - // if (!does_match) { - // this->at(0).print("this[0] = "); - // that.at(0).print("that[0] = "); - // std::cerr - // << "Cannot move a UniformMatrixList element of size (" << - // that.at(0).n_rows << "," << that.at(0).n_cols << ") for an - // element of size (" << dim_[0][0] << "," << dim_[0][1] << "). - // Skipping.\n"; - // return (*this); - // } - // } - // } - - dim_ = that.dim_; - std::vector::operator=(std::move(that)); - - return (*this); -} - -template -UniformMatrixList::UniformMatrixList(const std::vector& mats, - std::array dim) - : vector(mats) { - CheckDimensions(dim); -} - -template -UniformMatrixList::UniformMatrixList(std::vector&& mats, - std::array dim) - : vector(std::move(mats)) { - CheckDimensions(dim); -}; - -template -UniformMatrixList::UniformMatrixList(std::initializer_list mats, - std::array dim) - : vector(mats) { - CheckDimensions(dim); -}; - -template -UniformMatrixList::UniformMatrixList(const UniformMatrixList& that) - : vector(that) { - (*this) = that; -} - -template -UniformMatrixList::UniformMatrixList(UniformMatrixList&& that) noexcept - : vector(std::move(that)) { - for (size_t k = 0; k < this->size(); k++) { - std::array dim_k({this->at(k).n_rows, this->at(k).n_cols}); - dim_.push_back(dim_k); - } -} - -template -void UniformMatrixList::CheckDimensions(std::array dim) { - // change behavior based on free dim D - if ((dim[0] == 0) && !(D == kMatFreeDim1)) { - dim[0] = this->at(0).n_rows; - } - if ((dim[1] == 0) && !(D == kMatFreeDim2)) { - dim[1] = this->at(0).n_cols; - } - - // make sure dimensiolaties are all uniform - bool does_match(true); - for (const Matrix& mat : *this) { - if (!(D == kMatFreeDim1)) { - does_match = does_match && (mat.n_rows == dim[0]); - } - if (!(D == kMatFreeDim2)) { - does_match = does_match && (mat.n_cols == dim[1]); - } - if (!does_match) { - throw std::runtime_error( - "Dimensionality of one or more input matrices are not uniform."); - } - } - - dim_ = std::vector>(this->size(), dim); - for (size_t k = 0; k < this->size(); k++) { - dim_[k][0] = (*this)[k].n_rows; - dim_[k][1] = (*this)[k].n_cols; - } -} - -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_uniform_mats.h +summary: List of uniformly sized matrices. + +--- + +# ldsCtrlEst_h/lds_uniform_mats.h + +List of uniformly sized matrices. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::UniformMatrixList](/lds-ctrl-est/docs/api/classes/classlds_1_1_uniform_matrix_list/)** | + +## Detailed Description + + + +This file provides a container for uniformly sized matrices. Users may specify one dimension to be free to vary in the list. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_uniform_mats.h - Uniform Matrices ------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// Limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_UNIFORM_MATS_H +#define LDSCTRLEST_LDS_UNIFORM_MATS_H + +#include // std::array +#include // std::vector + +#include "lds.h" + +namespace lds { +template +class UniformMatrixList : public std::vector { + private: + // TODO(mfbolus): would rather *uncomment* the below for sake of conversion + // using std::vector::vector; + // don't allow push_back to be used since it doesn't check dims + using std::vector::push_back; + + public: + using std::vector::operator=; + using std::vector::operator[]; + using std::vector::begin; + using std::vector::end; + using std::vector::size; + using std::vector::at; + UniformMatrixList() = default; + + explicit UniformMatrixList(const std::vector& mats, + std::array dim = {0, 0}); + + explicit UniformMatrixList(std::vector&& mats, + std::array dim = {0, 0}); + + UniformMatrixList(std::initializer_list mats, + std::array dim = {0, 0}); + + UniformMatrixList(const UniformMatrixList& that); + + UniformMatrixList(UniformMatrixList&& that) noexcept; + + ~UniformMatrixList() = default; + + const std::array& dim(size_t n = 0) const { return dim_.at(n); } + + size_t size() { return std::vector::size(); }; + + const Matrix& at(size_t n) { return std::vector::at(n); }; + + void Swap(Matrix& that, size_t n); + + UniformMatrixList& operator=(const UniformMatrixList& that); + UniformMatrixList& operator=(UniformMatrixList&& that) noexcept; + void append(const Matrix& mat); + + private: + void CheckDimensions(std::array dim); + std::vector> dim_; +}; + +template +inline void UniformMatrixList::Swap(Matrix& that, size_t n) { + // make sure request in range + if (n >= this->size()) { + std::cerr + << "Requested UniformMatrixList element out of bounds. Skipping.\n"; + return; + } + // check dim + bool does_match = true; + if (!(D == kMatFreeDim1)) { + does_match = does_match && (dim_[0][0] == that.n_rows); + } + if (!(D == kMatFreeDim2)) { + does_match = does_match && (dim_[0][1] == that.n_cols); + } + if (!does_match) { + std::cerr << "Cannot swap a UniformMatrixList element for an element of " + "different size. Skipping.\n"; + return; + } + // if checks pass, perform swap + // not moving, since it causes memory issues. + // so this method isn't a memory-saver as designed for now + Matrix tmp = (*this)[n]; + (*this)[n] = that; + that = tmp; + + if (D == kMatFreeDim1) { + this->dim_[n][0] = (*this)[n].n_rows; + } + if (D == kMatFreeDim2) { + this->dim_[n][1] = (*this)[n].n_cols; + } +} + +template +void UniformMatrixList::append(const Matrix& mat) { + std::array dim({mat.n_rows, mat.n_cols}); + CheckDimensions(dim); + std::vector::push_back(mat); + dim_.push_back(dim); +} + +template +inline UniformMatrixList& UniformMatrixList::operator=( + const UniformMatrixList& that) { + // make sure dim_ vector is initialized + if (dim_.empty()) { + dim_ = std::vector>(that.size(), {0, 0}); + } + // check dimensions + if (!this->empty()) { + if (this->size() != that.size()) { + std::ostringstream ss; + ss << "cannot reassign " << this->size() << " matrices with " + << that.size() << " matrices"; + throw std::runtime_error(ss.str()); + } + + // if dimensions a not zero and do not match, skip move with error message. + bool dims_nonzero = true; + for (auto d : dim_) { + if (!(D == kMatFreeDim1) && d[0] < 1) { + dims_nonzero = false; + break; + } + if (!(D == kMatFreeDim2) && d[1] < 1) { + dims_nonzero = false; + break; + } + } + if (dims_nonzero) { + bool does_match = true; + if (!(D == kMatFreeDim1)) { + does_match = does_match && (dim_[0][0] == that.at(0).n_rows); + } + if (!(D == kMatFreeDim2)) { + does_match = does_match && (dim_[0][1] == that.at(0).n_cols); + } + if (!does_match) { + std::ostringstream ss; + ss << "cannot reassign matrices of size " << dim_[0][0] << "x" + << dim_[0][1] << " with matrices of size " << that.at(0).n_rows + << "x" << that.at(0).n_cols; + throw std::runtime_error(ss.str()); + } + } + } + + for (size_t k = 0; k < this->size(); k++) { + (*this)[k] = that[k]; + dim_[k] = that.dim(k); + } + + return (*this); +} + +template +inline UniformMatrixList& UniformMatrixList::operator=( + UniformMatrixList&& that) noexcept { + // // check dimensions + // // if empty, assume a default constructed object and safe to move + // if (!this->empty()) { + // if (this->size() != that.size()) { + // std::cerr << "Cannot reassign " << this->size() << " matrices with " + // << that.size() << " matrices. Skipping.\n"; + // return (*this); + // } + // + // // if dimensions a not zero and do not match, skip move with error + // message. bool dims_nonzero = true; for (auto d : dim_) { + // if (!(D == kMatFreeDim1) && (d[0] < 1)) { + // dims_nonzero = false; + // break; + // } + // if (!(D == kMatFreeDim2) && (d[1] < 1)) { + // dims_nonzero = false; + // break; + // } + // } + // + // if (dims_nonzero) { + // bool does_match = true; + // if (!(D == kMatFreeDim1)) { + // does_match = does_match && (dim_[0][0] == that.at(0).n_rows); + // } + // + // if (!(D == kMatFreeDim2)) { + // does_match = does_match && (dim_[0][1] == that.at(0).n_cols); + // } + // + // if (!does_match) { + // this->at(0).print("this[0] = "); + // that.at(0).print("that[0] = "); + // std::cerr + // << "Cannot move a UniformMatrixList element of size (" << + // that.at(0).n_rows << "," << that.at(0).n_cols << ") for an + // element of size (" << dim_[0][0] << "," << dim_[0][1] << "). + // Skipping.\n"; + // return (*this); + // } + // } + // } + + dim_ = that.dim_; + std::vector::operator=(std::move(that)); + + return (*this); +} + +template +UniformMatrixList::UniformMatrixList(const std::vector& mats, + std::array dim) + : vector(mats) { + CheckDimensions(dim); +} + +template +UniformMatrixList::UniformMatrixList(std::vector&& mats, + std::array dim) + : vector(std::move(mats)) { + CheckDimensions(dim); +}; + +template +UniformMatrixList::UniformMatrixList(std::initializer_list mats, + std::array dim) + : vector(mats) { + CheckDimensions(dim); +}; + +template +UniformMatrixList::UniformMatrixList(const UniformMatrixList& that) + : vector(that) { + (*this) = that; +} + +template +UniformMatrixList::UniformMatrixList(UniformMatrixList&& that) noexcept + : vector(std::move(that)) { + for (size_t k = 0; k < this->size(); k++) { + std::array dim_k({this->at(k).n_rows, this->at(k).n_cols}); + dim_.push_back(dim_k); + } +} + +template +void UniformMatrixList::CheckDimensions(std::array dim) { + // change behavior based on free dim D + if ((dim[0] == 0) && !(D == kMatFreeDim1)) { + dim[0] = this->at(0).n_rows; + } + if ((dim[1] == 0) && !(D == kMatFreeDim2)) { + dim[1] = this->at(0).n_cols; + } + + // make sure dimensiolaties are all uniform + bool does_match(true); + for (const Matrix& mat : *this) { + if (!(D == kMatFreeDim1)) { + does_match = does_match && (mat.n_rows == dim[0]); + } + if (!(D == kMatFreeDim2)) { + does_match = does_match && (mat.n_cols == dim[1]); + } + if (!does_match) { + throw std::runtime_error( + "Dimensionality of one or more input matrices are not uniform."); + } + } + + dim_ = std::vector>(this->size(), dim); + for (size_t k = 0; k < this->size(); k++) { + dim_[k][0] = (*this)[k].n_rows; + dim_[k][1] = (*this)[k].n_cols; + } +} + +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__uniform__systems_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__uniform__systems_8h.md index 33c86e2f..f93df607 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__uniform__systems_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__uniform__systems_8h.md @@ -1,268 +1,268 @@ ---- -title: ldsCtrlEst_h/lds_uniform_systems.h -summary: List of uniformly sized Systems. - ---- - -# ldsCtrlEst_h/lds_uniform_systems.h - -List of uniformly sized Systems. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::UniformSystemList](/lds-ctrl-est/docs/api/classes/classlds_1_1uniformsystemlist/)** | - -## Detailed Description - - - -This file provides a container for uniformly sized Systems. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_uniform_systems.h - Uniform Systems ----*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// Limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_UNIFORM_SYSTEMS_H -#define LDSCTRLEST_LDS_UNIFORM_SYSTEMS_H - -#include // std::array -#include // std::vector - -// namespace -#include "lds.h" -// System type -#include "lds_sys.h" - -namespace lds { -template -class UniformSystemList : public std::vector { - static_assert(std::is_base_of::value, - "System must be derived from lds::System type."); - - private: - // TODO(mfbolus): would rather *uncomment* the below for sake of conversion - // using std::vector::vector; - using std::vector::operator=; - using std::vector::operator[]; - using std::vector::at; - using std::vector::begin; - using std::vector::end; - using std::vector::size; - - public: - UniformSystemList() = default; - - explicit UniformSystemList(const std::vector& systems, - std::array dim = {0, 0, 0}); - - explicit UniformSystemList(std::vector&& systems, - std::array dim = {0, 0, 0}); - - UniformSystemList(std::initializer_list systems, - std::array dim = {0, 0, 0}); - - UniformSystemList(const UniformSystemList& that); - UniformSystemList(UniformSystemList&& that) noexcept; - - ~UniformSystemList() = default; - - const std::array& dim() const { return dim_; } - - size_t size() { return std::vector::size(); }; - - const System& at(size_t n) { return std::vector::at(n); }; - - void Swap(System& that, size_t n); - - UniformSystemList& operator=(const UniformSystemList& that); - UniformSystemList& operator=(UniformSystemList&& that) noexcept; - - private: - void CheckDimensions(std::array dim); - std::array dim_{}; -}; - -template -inline void UniformSystemList::Swap(System& that, size_t n) { - // make sure request in range - if (n >= this->size()) { - std::cerr - << "Requested UniformSystemList element out of bounds. Skipping.\n"; - return; - } - // check dim - bool does_match = (dim_[0] == that.n_u()) && (dim_[1] == that.n_x()) && - (dim_[2] == that.n_y()); - if (!does_match) { - std::cerr << "Cannot swap a UniformSystemList element for an element of " - "different size. Skipping.\n"; - return; - } - // if checks pass, perform swap - System tmp = std::move((*this)[n]); - (*this)[n] = std::move(that); - that = std::move(tmp); -} - -template -inline UniformSystemList& UniformSystemList::operator=( - const UniformSystemList& that) { - // check dimensions - if (!this->empty()) { - if (this->size() != that.size()) { - std::ostringstream ss; - ss << "cannot reassign " << this->size() << " systems with " - << that.size() << " systems"; - throw std::runtime_error(ss.str()); - } - - if (dim_[0] + dim_[1] + dim_[2]) { - std::array other_dim(that.dim()); - if (dim_ != other_dim) { - std::ostringstream ss; - ss << "cannot reassign systems of size " << dim_[0] << "x" << dim_[1] - << "x" << dim_[2] << " with systems of size " << other_dim[0] << "x" - << other_dim[1] << "x" << dim_[2]; - throw std::runtime_error(ss.str()); - } - } - } - - for (size_t k = 0; k < this->size(); k++) { - (*this)[k] = that[k]; - } - return (*this); -} - -template -inline UniformSystemList& UniformSystemList::operator=( - UniformSystemList&& that) noexcept { - // // check dimensions - // // if empty, assume a default constructed object and safe to move - // if (!this->empty()) { - // if (this->size() != that.size()) { - // std::cerr << "Cannot reassign " << this->size() << " systems with " - // << that.size() << " systems. Skipping.\n"; - // return (*this); - // } - // - // // if dimensions a not zero and do not match, skip move with error - // message. if (dim_[0] + dim_[1] + dim_[2]) { - // bool does_match = (dim_[0] == that.at(0).n_u()) && - // (dim_[1] == that.at(0).n_x()) && - // (dim_[2] == that.at(0).n_y()); - // if (!does_match) { - // std::cerr - // << "Cannot move a UniformSystemList element for an element of " - // "different size. Skipping.\n"; - // return (*this); - // } - // } - // } - - dim_ = that.dim_; - std::vector::operator=(std::move(that)); - - return (*this); -} - -template -UniformSystemList::UniformSystemList(const std::vector& systems, - std::array dim) - : std::vector(systems) { - CheckDimensions(dim); -} - -template -UniformSystemList::UniformSystemList(std::vector&& systems, - std::array dim) - : std::vector(std::move(systems)) { - CheckDimensions(dim); -}; - -template -UniformSystemList::UniformSystemList( - std::initializer_list systems, std::array dim) - : std::vector(systems) { - CheckDimensions(dim); -}; - -template -UniformSystemList::UniformSystemList(const UniformSystemList& that) - : std::vector(that) { - (*this) = that; -} - -template -UniformSystemList::UniformSystemList(UniformSystemList&& that) noexcept - : std::vector(std::move(that)) { - this->dim_[0] = this->at(0).n_u(); - this->dim_[1] = this->at(0).n_x(); - this->dim_[2] = this->at(0).n_y(); -} - -template -void UniformSystemList::CheckDimensions(std::array dim) { - if (dim[0] + dim[1] + dim[2]) { - dim_ = dim; - } else { - dim_[0] = this->at(0).n_u(); - dim_[1] = this->at(0).n_x(); - dim_[2] = this->at(0).n_y(); - } - - // make sure dimensiolaties are all uniform - bool does_match(true); - for (const System& sys : *this) { - does_match = does_match && (sys.n_u() == dim_[0]); - does_match = does_match && (sys.n_x() == dim_[1]); - does_match = does_match && (sys.n_y() == dim_[2]); - if (!does_match) { - throw std::runtime_error( - "Dimensionality of one or more input systems are not uniform."); - } - } -} - -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_uniform_systems.h +summary: List of uniformly sized Systems. + +--- + +# ldsCtrlEst_h/lds_uniform_systems.h + +List of uniformly sized Systems. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::UniformSystemList](/lds-ctrl-est/docs/api/classes/classlds_1_1_uniform_system_list/)** | + +## Detailed Description + + + +This file provides a container for uniformly sized Systems. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_uniform_systems.h - Uniform Systems ----*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// Limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_UNIFORM_SYSTEMS_H +#define LDSCTRLEST_LDS_UNIFORM_SYSTEMS_H + +#include // std::array +#include // std::vector + +// namespace +#include "lds.h" +// System type +#include "lds_sys.h" + +namespace lds { +template +class UniformSystemList : public std::vector { + static_assert(std::is_base_of::value, + "System must be derived from lds::System type."); + + private: + // TODO(mfbolus): would rather *uncomment* the below for sake of conversion + // using std::vector::vector; + using std::vector::operator=; + using std::vector::operator[]; + using std::vector::at; + using std::vector::begin; + using std::vector::end; + using std::vector::size; + + public: + UniformSystemList() = default; + + explicit UniformSystemList(const std::vector& systems, + std::array dim = {0, 0, 0}); + + explicit UniformSystemList(std::vector&& systems, + std::array dim = {0, 0, 0}); + + UniformSystemList(std::initializer_list systems, + std::array dim = {0, 0, 0}); + + UniformSystemList(const UniformSystemList& that); + UniformSystemList(UniformSystemList&& that) noexcept; + + ~UniformSystemList() = default; + + const std::array& dim() const { return dim_; } + + size_t size() { return std::vector::size(); }; + + const System& at(size_t n) { return std::vector::at(n); }; + + void Swap(System& that, size_t n); + + UniformSystemList& operator=(const UniformSystemList& that); + UniformSystemList& operator=(UniformSystemList&& that) noexcept; + + private: + void CheckDimensions(std::array dim); + std::array dim_{}; +}; + +template +inline void UniformSystemList::Swap(System& that, size_t n) { + // make sure request in range + if (n >= this->size()) { + std::cerr + << "Requested UniformSystemList element out of bounds. Skipping.\n"; + return; + } + // check dim + bool does_match = (dim_[0] == that.n_u()) && (dim_[1] == that.n_x()) && + (dim_[2] == that.n_y()); + if (!does_match) { + std::cerr << "Cannot swap a UniformSystemList element for an element of " + "different size. Skipping.\n"; + return; + } + // if checks pass, perform swap + System tmp = std::move((*this)[n]); + (*this)[n] = std::move(that); + that = std::move(tmp); +} + +template +inline UniformSystemList& UniformSystemList::operator=( + const UniformSystemList& that) { + // check dimensions + if (!this->empty()) { + if (this->size() != that.size()) { + std::ostringstream ss; + ss << "cannot reassign " << this->size() << " systems with " + << that.size() << " systems"; + throw std::runtime_error(ss.str()); + } + + if (dim_[0] + dim_[1] + dim_[2]) { + std::array other_dim(that.dim()); + if (dim_ != other_dim) { + std::ostringstream ss; + ss << "cannot reassign systems of size " << dim_[0] << "x" << dim_[1] + << "x" << dim_[2] << " with systems of size " << other_dim[0] << "x" + << other_dim[1] << "x" << dim_[2]; + throw std::runtime_error(ss.str()); + } + } + } + + for (size_t k = 0; k < this->size(); k++) { + (*this)[k] = that[k]; + } + return (*this); +} + +template +inline UniformSystemList& UniformSystemList::operator=( + UniformSystemList&& that) noexcept { + // // check dimensions + // // if empty, assume a default constructed object and safe to move + // if (!this->empty()) { + // if (this->size() != that.size()) { + // std::cerr << "Cannot reassign " << this->size() << " systems with " + // << that.size() << " systems. Skipping.\n"; + // return (*this); + // } + // + // // if dimensions a not zero and do not match, skip move with error + // message. if (dim_[0] + dim_[1] + dim_[2]) { + // bool does_match = (dim_[0] == that.at(0).n_u()) && + // (dim_[1] == that.at(0).n_x()) && + // (dim_[2] == that.at(0).n_y()); + // if (!does_match) { + // std::cerr + // << "Cannot move a UniformSystemList element for an element of " + // "different size. Skipping.\n"; + // return (*this); + // } + // } + // } + + dim_ = that.dim_; + std::vector::operator=(std::move(that)); + + return (*this); +} + +template +UniformSystemList::UniformSystemList(const std::vector& systems, + std::array dim) + : std::vector(systems) { + CheckDimensions(dim); +} + +template +UniformSystemList::UniformSystemList(std::vector&& systems, + std::array dim) + : std::vector(std::move(systems)) { + CheckDimensions(dim); +}; + +template +UniformSystemList::UniformSystemList( + std::initializer_list systems, std::array dim) + : std::vector(systems) { + CheckDimensions(dim); +}; + +template +UniformSystemList::UniformSystemList(const UniformSystemList& that) + : std::vector(that) { + (*this) = that; +} + +template +UniformSystemList::UniformSystemList(UniformSystemList&& that) noexcept + : std::vector(std::move(that)) { + this->dim_[0] = this->at(0).n_u(); + this->dim_[1] = this->at(0).n_x(); + this->dim_[2] = this->at(0).n_y(); +} + +template +void UniformSystemList::CheckDimensions(std::array dim) { + if (dim[0] + dim[1] + dim[2]) { + dim_ = dim; + } else { + dim_[0] = this->at(0).n_u(); + dim_[1] = this->at(0).n_x(); + dim_[2] = this->at(0).n_y(); + } + + // make sure dimensiolaties are all uniform + bool does_match(true); + for (const System& sys : *this) { + does_match = does_match && (sys.n_u() == dim_[0]); + does_match = does_match && (sys.n_x() == dim_[1]); + does_match = does_match && (sys.n_y() == dim_[2]); + if (!does_match) { + throw std::runtime_error( + "Dimensionality of one or more input systems are not uniform."); + } + } +} + +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__uniform__vecs_8cpp.md b/misc/docs-hugo/content/docs/api/Files/lds__uniform__vecs_8cpp.md index 1d6a78af..93b59d7c 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__uniform__vecs_8cpp.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__uniform__vecs_8cpp.md @@ -1,107 +1,107 @@ ---- -title: src/lds_uniform_vecs.cpp -summary: Uniformly sized vectors. - ---- - -# src/lds_uniform_vecs.cpp - -Uniformly sized vectors. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Detailed Description - - - -This file provides a container for uniformly sized vectors. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_uniform_vecs.cpp - Uniform Matrices --------------===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// Limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#include - -namespace lds { - -UniformVectorList::UniformVectorList(const std::vector& vecs, - size_t dim) - : vector(vecs) { - CheckDimensions(dim); -} - -UniformVectorList::UniformVectorList(std::vector&& vecs, size_t dim) - : vector(std::move(vecs)) { - CheckDimensions(dim); -}; - -UniformVectorList::UniformVectorList(std::initializer_list vecs, - size_t dim) - : vector(vecs) { - CheckDimensions(dim); -}; - -UniformVectorList::UniformVectorList(const UniformVectorList& that) - : vector(that) { - (*this) = that; -} - -UniformVectorList::UniformVectorList(UniformVectorList&& that) noexcept - : vector(std::move(that)) { - this->dim_ = this->at(0).n_elem; -} - -void UniformVectorList::CheckDimensions(size_t dim) { - if (dim) { - dim_ = dim; - } else { - dim_ = this->at(0).n_elem; - } - - // make sure dimensiolaties are all uniform - bool does_match(true); - for (const Vector& vec : *this) { - does_match = does_match && (vec.n_elem == dim_); - if (!does_match) { - throw std::runtime_error( - "Dimensionality of one or more input matrices are not uniform."); - } - } -} - -} // namespace lds -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: src/lds_uniform_vecs.cpp +summary: Uniformly sized vectors. + +--- + +# src/lds_uniform_vecs.cpp + +Uniformly sized vectors. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Detailed Description + + + +This file provides a container for uniformly sized vectors. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_uniform_vecs.cpp - Uniform Matrices --------------===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// Limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#include + +namespace lds { + +UniformVectorList::UniformVectorList(const std::vector& vecs, + size_t dim) + : vector(vecs) { + CheckDimensions(dim); +} + +UniformVectorList::UniformVectorList(std::vector&& vecs, size_t dim) + : vector(std::move(vecs)) { + CheckDimensions(dim); +}; + +UniformVectorList::UniformVectorList(std::initializer_list vecs, + size_t dim) + : vector(vecs) { + CheckDimensions(dim); +}; + +UniformVectorList::UniformVectorList(const UniformVectorList& that) + : vector(that) { + (*this) = that; +} + +UniformVectorList::UniformVectorList(UniformVectorList&& that) noexcept + : vector(std::move(that)) { + this->dim_ = this->at(0).n_elem; +} + +void UniformVectorList::CheckDimensions(size_t dim) { + if (dim) { + dim_ = dim; + } else { + dim_ = this->at(0).n_elem; + } + + // make sure dimensiolaties are all uniform + bool does_match(true); + for (const Vector& vec : *this) { + does_match = does_match && (vec.n_elem == dim_); + if (!does_match) { + throw std::runtime_error( + "Dimensionality of one or more input matrices are not uniform."); + } + } +} + +} // namespace lds +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/lds__uniform__vecs_8h.md b/misc/docs-hugo/content/docs/api/Files/lds__uniform__vecs_8h.md index 620ae01e..782a4b4b 100644 --- a/misc/docs-hugo/content/docs/api/Files/lds__uniform__vecs_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/lds__uniform__vecs_8h.md @@ -1,192 +1,192 @@ ---- -title: ldsCtrlEst_h/lds_uniform_vecs.h -summary: List of uniformly sized vectors. - ---- - -# ldsCtrlEst_h/lds_uniform_vecs.h - -List of uniformly sized vectors. [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::UniformVectorList](/lds-ctrl-est/docs/api/classes/classlds_1_1uniformvectorlist/)** | - -## Detailed Description - - - -This file provides a container for uniformly sized vectors. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/lds_uniform_vecs.h - Uniform Vectors -------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// Limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_LDS_UNIFORM_VECS_H -#define LDSCTRLEST_LDS_UNIFORM_VECS_H - -#include // std::array -#include // std::vector - -#include "lds.h" - -namespace lds { - -class UniformVectorList : public std::vector { - private: - // TODO(mfbolus): would rather *uncomment* the below for sake of conversion - // using std::vector::vector; - using std::vector::operator=; - using std::vector::operator[]; - using std::vector::at; - using std::vector::begin; - using std::vector::end; - using std::vector::size; - - public: - UniformVectorList() = default; - - explicit UniformVectorList(const std::vector& vecs, size_t dim = 0); - - explicit UniformVectorList(std::vector&& vecs, size_t dim = 0); - - UniformVectorList(std::initializer_list vecs, size_t dim = 0); - - UniformVectorList(const UniformVectorList& that); - UniformVectorList(UniformVectorList&& that) noexcept; - ~UniformVectorList() = default; - - size_t dim() const { return dim_; } - - size_t size() { return std::vector::size(); }; - - const Vector& at(size_t n) { return std::vector::at(n); }; - - void Swap(Vector& that, size_t n); - - UniformVectorList& operator=(const UniformVectorList& that); - UniformVectorList& operator=(UniformVectorList&& that) noexcept; - - private: - void CheckDimensions(size_t dim); - size_t dim_{}; -}; - -inline void UniformVectorList::Swap(Vector& that, size_t n) { - // make sure request in range - if (n >= this->size()) { - std::cerr - << "Requested UniformMatrixList element out of bounds. Skipping.\n"; - return; - } - // check dim - bool does_match = dim_ == that.n_elem; - if (!does_match) { - std::cerr << "Cannot swap a UniformMatrixList element for an element of " - "different size. Skipping.\n"; - return; - } - // if checks pass, perform swap - Vector tmp = std::move((*this)[n]); - (*this)[n] = std::move(that); - that = std::move(tmp); -} - -inline UniformVectorList& UniformVectorList::operator=( - const UniformVectorList& that) { - // check dimensions - if (!this->empty()) { - if (this->size() != that.size()) { - std::ostringstream ss; - ss << "cannot reassign " << this->size() << " vectors with " - << that.size() << " vectors"; - throw std::runtime_error(ss.str()); - } - - if (dim_) { - size_t other_dim(that.dim()); - if (dim_ != other_dim) { - std::ostringstream ss; - ss << "cannot reassign vectors of size " << dim_ - << " with vectors of size " << other_dim; - throw std::runtime_error(ss.str()); - } - } - } - - for (size_t k = 0; k < this->size(); k++) { - (*this)[k] = that[k]; - } - - return (*this); -} - -inline UniformVectorList& UniformVectorList::operator=( - UniformVectorList&& that) noexcept { - // // check dimensions - // if (!this->empty()) { - // if (this->size() != that.size()) { - // std::cerr << "Cannot reassign " << this->size() << " vectors with " - // << that.size() << " vectors. Skipping.\n"; - // return (*this); - // } - // - // if (dim_) { - // size_t other_dim(that.dim()); - // if (dim_ != other_dim) { - // std::cerr << "Cannot reassign vectors of size " << dim_ - // << " with matrices of size " << other_dim << ". - // Skipping.\n"; - // return (*this); - // } - // } - // } - - dim_ = that.dim_; - std::vector::operator=(std::move(that)); - - return (*this); -} - -} // namespace lds - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/lds_uniform_vecs.h +summary: List of uniformly sized vectors. + +--- + +# ldsCtrlEst_h/lds_uniform_vecs.h + +List of uniformly sized vectors. [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[lds](/lds-ctrl-est/docs/api/namespaces/namespacelds/)**
Linear Dynamical Systems (LDS) namespace. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::UniformVectorList](/lds-ctrl-est/docs/api/classes/classlds_1_1_uniform_vector_list/)** | + +## Detailed Description + + + +This file provides a container for uniformly sized vectors. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/lds_uniform_vecs.h - Uniform Vectors -------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// Limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_LDS_UNIFORM_VECS_H +#define LDSCTRLEST_LDS_UNIFORM_VECS_H + +#include // std::array +#include // std::vector + +#include "lds.h" + +namespace lds { + +class UniformVectorList : public std::vector { + private: + // TODO(mfbolus): would rather *uncomment* the below for sake of conversion + // using std::vector::vector; + using std::vector::operator=; + using std::vector::operator[]; + using std::vector::at; + using std::vector::begin; + using std::vector::end; + using std::vector::size; + + public: + UniformVectorList() = default; + + explicit UniformVectorList(const std::vector& vecs, size_t dim = 0); + + explicit UniformVectorList(std::vector&& vecs, size_t dim = 0); + + UniformVectorList(std::initializer_list vecs, size_t dim = 0); + + UniformVectorList(const UniformVectorList& that); + UniformVectorList(UniformVectorList&& that) noexcept; + ~UniformVectorList() = default; + + size_t dim() const { return dim_; } + + size_t size() { return std::vector::size(); }; + + const Vector& at(size_t n) { return std::vector::at(n); }; + + void Swap(Vector& that, size_t n); + + UniformVectorList& operator=(const UniformVectorList& that); + UniformVectorList& operator=(UniformVectorList&& that) noexcept; + + private: + void CheckDimensions(size_t dim); + size_t dim_{}; +}; + +inline void UniformVectorList::Swap(Vector& that, size_t n) { + // make sure request in range + if (n >= this->size()) { + std::cerr + << "Requested UniformMatrixList element out of bounds. Skipping.\n"; + return; + } + // check dim + bool does_match = dim_ == that.n_elem; + if (!does_match) { + std::cerr << "Cannot swap a UniformMatrixList element for an element of " + "different size. Skipping.\n"; + return; + } + // if checks pass, perform swap + Vector tmp = std::move((*this)[n]); + (*this)[n] = std::move(that); + that = std::move(tmp); +} + +inline UniformVectorList& UniformVectorList::operator=( + const UniformVectorList& that) { + // check dimensions + if (!this->empty()) { + if (this->size() != that.size()) { + std::ostringstream ss; + ss << "cannot reassign " << this->size() << " vectors with " + << that.size() << " vectors"; + throw std::runtime_error(ss.str()); + } + + if (dim_) { + size_t other_dim(that.dim()); + if (dim_ != other_dim) { + std::ostringstream ss; + ss << "cannot reassign vectors of size " << dim_ + << " with vectors of size " << other_dim; + throw std::runtime_error(ss.str()); + } + } + } + + for (size_t k = 0; k < this->size(); k++) { + (*this)[k] = that[k]; + } + + return (*this); +} + +inline UniformVectorList& UniformVectorList::operator=( + UniformVectorList&& that) noexcept { + // // check dimensions + // if (!this->empty()) { + // if (this->size() != that.size()) { + // std::cerr << "Cannot reassign " << this->size() << " vectors with " + // << that.size() << " vectors. Skipping.\n"; + // return (*this); + // } + // + // if (dim_) { + // size_t other_dim(that.dim()); + // if (dim_ != other_dim) { + // std::cerr << "Cannot reassign vectors of size " << dim_ + // << " with matrices of size " << other_dim << ". + // Skipping.\n"; + // return (*this); + // } + // } + // } + + dim_ = that.dim_; + std::vector::operator=(std::move(that)); + + return (*this); +} + +} // namespace lds + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/mex__c__util_8h.md b/misc/docs-hugo/content/docs/api/Files/mex__c__util_8h.md index c64256a1..bbe9a6a7 100644 --- a/misc/docs-hugo/content/docs/api/Files/mex__c__util_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/mex__c__util_8h.md @@ -1,132 +1,132 @@ ---- -title: ldsCtrlEst_h/mex_c_util.h -summary: arma <-> mex interoperability utilities (Matlab C API) - ---- - -# ldsCtrlEst_h/mex_c_util.h - -arma <-> mex interoperability utilities (Matlab C API) [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[armamexc](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/)**
arma/mex interface using Matlab C API | - -## Detailed Description - - - -This file defines utility functions for interoperability between armadillo and Matlab/Octave's C mex API. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/mex_c_util.h - Mex C API Utilities ---------*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_MEXC_UTIL_H -#define LDSCTRLEST_MEXC_UTIL_H - -#include - -#include "mex.h" - -// // If Matlab_FOUND, include matrix.h. -// // (Octave does not need/have it.) -// #ifdef Matlab_FOUND -// #include "matrix.h" -// #endif - -namespace armamexc { -template -inline auto m2T_scalar(const mxArray *matlab_scalar) -> T { - if (mxGetData(matlab_scalar)) { - return static_cast(mxGetScalar(matlab_scalar)); - } - mexErrMsgTxt("No data available."); - return 0; -} - -template -inline auto m2a_mat(const mxArray *matlab_mat, bool copy_aux_mem = false, - bool strict = true) -> arma::Mat { - if (mxGetData(matlab_mat)) { - const mwSize n_dim = mxGetNumberOfDimensions(matlab_mat); - if (n_dim == 2) { - return arma::Mat(static_cast(mxGetData(matlab_mat)), - mxGetM(matlab_mat), mxGetN(matlab_mat), copy_aux_mem, - strict); - } - mexErrMsgTxt("Number of dimensions must be 2."); - return arma::Mat(); - } - mexErrMsgTxt("No data available."); - return arma::Mat(); -} - -// TODO(mfbolus): make these templated. - -template -inline auto a2m_mat(arma::Mat const &arma_mat) -> mxArray * { - mxArray *matlab_mat = mxCreateNumericMatrix(arma_mat.n_rows, arma_mat.n_cols, - mxDOUBLE_CLASS, mxREAL); - if (matlab_mat) { - auto *dst_pointer = static_cast(mxGetData(matlab_mat)); - const auto *src_pointer = const_cast(arma_mat.memptr()); - // TODO(mfbolus): I just want to MOVE the data, not copy. - std::memcpy(dst_pointer, src_pointer, sizeof(T) * arma_mat.n_elem); - return matlab_mat; - } - mexErrMsgTxt("Failed to create matlab mat from arma::Mat."); - return nullptr; -} - -template -inline auto a2m_vec(arma::Col const &arma_vec) -> mxArray * { - mxArray *matlab_mat = - mxCreateNumericMatrix(arma_vec.n_elem, 1, mxDOUBLE_CLASS, mxREAL); - if (matlab_mat) { - auto *dst_pointer = static_cast(mxGetData(matlab_mat)); - const auto *src_pointer = const_cast(arma_vec.memptr()); - // TODO(mfbolus): I just want to MOVE the data, not copy. - std::memcpy(dst_pointer, src_pointer, sizeof(T) * arma_vec.n_elem); - return matlab_mat; - } - mexErrMsgTxt("Failed to create matlab mat from arma::Col."); - return nullptr; -} - -} // namespace armamexc - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/mex_c_util.h +summary: arma <-> mex interoperability utilities (Matlab C API) + +--- + +# ldsCtrlEst_h/mex_c_util.h + +arma <-> mex interoperability utilities (Matlab C API) [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[armamexc](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/)**
arma/mex interface using Matlab C API | + +## Detailed Description + + + +This file defines utility functions for interoperability between armadillo and Matlab/Octave's C mex API. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/mex_c_util.h - Mex C API Utilities ---------*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_MEXC_UTIL_H +#define LDSCTRLEST_MEXC_UTIL_H + +#include + +#include "mex.h" + +// // If Matlab_FOUND, include matrix.h. +// // (Octave does not need/have it.) +// #ifdef Matlab_FOUND +// #include "matrix.h" +// #endif + +namespace armamexc { +template +inline auto m2T_scalar(const mxArray *matlab_scalar) -> T { + if (mxGetData(matlab_scalar)) { + return static_cast(mxGetScalar(matlab_scalar)); + } + mexErrMsgTxt("No data available."); + return 0; +} + +template +inline auto m2a_mat(const mxArray *matlab_mat, bool copy_aux_mem = false, + bool strict = true) -> arma::Mat { + if (mxGetData(matlab_mat)) { + const mwSize n_dim = mxGetNumberOfDimensions(matlab_mat); + if (n_dim == 2) { + return arma::Mat(static_cast(mxGetData(matlab_mat)), + mxGetM(matlab_mat), mxGetN(matlab_mat), copy_aux_mem, + strict); + } + mexErrMsgTxt("Number of dimensions must be 2."); + return arma::Mat(); + } + mexErrMsgTxt("No data available."); + return arma::Mat(); +} + +// TODO(mfbolus): make these templated. + +template +inline auto a2m_mat(arma::Mat const &arma_mat) -> mxArray * { + mxArray *matlab_mat = mxCreateNumericMatrix(arma_mat.n_rows, arma_mat.n_cols, + mxDOUBLE_CLASS, mxREAL); + if (matlab_mat) { + auto *dst_pointer = static_cast(mxGetData(matlab_mat)); + const auto *src_pointer = const_cast(arma_mat.memptr()); + // TODO(mfbolus): I just want to MOVE the data, not copy. + std::memcpy(dst_pointer, src_pointer, sizeof(T) * arma_mat.n_elem); + return matlab_mat; + } + mexErrMsgTxt("Failed to create matlab mat from arma::Mat."); + return nullptr; +} + +template +inline auto a2m_vec(arma::Col const &arma_vec) -> mxArray * { + mxArray *matlab_mat = + mxCreateNumericMatrix(arma_vec.n_elem, 1, mxDOUBLE_CLASS, mxREAL); + if (matlab_mat) { + auto *dst_pointer = static_cast(mxGetData(matlab_mat)); + const auto *src_pointer = const_cast(arma_vec.memptr()); + // TODO(mfbolus): I just want to MOVE the data, not copy. + std::memcpy(dst_pointer, src_pointer, sizeof(T) * arma_vec.n_elem); + return matlab_mat; + } + mexErrMsgTxt("Failed to create matlab mat from arma::Col."); + return nullptr; +} + +} // namespace armamexc + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Files/mex__cpp__util_8h.md b/misc/docs-hugo/content/docs/api/Files/mex__cpp__util_8h.md index b8dec155..df9fa95e 100644 --- a/misc/docs-hugo/content/docs/api/Files/mex__cpp__util_8h.md +++ b/misc/docs-hugo/content/docs/api/Files/mex__cpp__util_8h.md @@ -1,153 +1,153 @@ ---- -title: ldsCtrlEst_h/mex_cpp_util.h -summary: arma <-> mex interoperability utilities (Matlab C++ API) - ---- - -# ldsCtrlEst_h/mex_cpp_util.h - -arma <-> mex interoperability utilities (Matlab C++ API) [More...](#detailed-description) - - - -## Namespaces - -| Name | -| -------------- | -| **[armamexcpp](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/)**
arma/mex interface using Matlab C++ API | - -## Detailed Description - - - -This file defines utility functions for interoperability between armadillo and Matlab's C++ mex API. - - - - - -## Source code - -```cpp -//===-- ldsCtrlEst_h/mex_cpp_util.h - Mex C++ API Utilities -----*- C++ -*-===// -// -// Copyright 2021 Michael Bolus -// Copyright 2021 Georgia Institute of Technology -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// - -#ifndef LDSCTRLEST_MEXCPP_UTIL_H -#define LDSCTRLEST_MEXCPP_UTIL_H - -#include - -#include "mex.hpp" -#include "mexAdapter.hpp" - -namespace armamexcpp { -template -std::vector> m2a_cellmat(matlab::data::CellArray& matlab_cell) { - size_t n_cells = matlab_cell.getNumberOfElements(); - std::vector> arma_mat(n_cells, - arma::Mat(1, 1, arma::fill::zeros)); - for (size_t k = 0; k < n_cells; k++) { - matlab::data::TypedArray matlab_mat = matlab_cell[k]; - auto dims = matlab_mat.getDimensions(); - arma_mat[k] = arma::Mat(matlab_mat.release().get(), dims[0], dims[1]); - } - return arma_mat; -}; - -template -std::vector m2s_vec(matlab::data::TypedArray& matlab_array) { - size_t n_elem = matlab_array.getNumberOfElements(); - T* ptr = matlab_array.release().get(); - std::vector vec(ptr, ptr + n_elem); - return vec; -}; - -template -arma::Col m2a_vec(matlab::data::TypedArray matlab_array) { - size_t n_elem = matlab_array.getNumberOfElements(); - // T* ptr = matlab_array.release().get(); - // arma::Col vec(ptr, n_elem); //, false); - // TODO(mfbolus): for some reason, using the above pointer at times leads to - // getting garbage values. matlab array values may be stored in non-contiguous - // memory? - arma::Col vec(n_elem, arma::fill::zeros); - for (size_t k = 0; k < n_elem; k++) { - vec[k] = matlab_array[k]; - } - return vec; -}; - -template -arma::Mat m2a_mat(matlab::data::TypedArray matlab_array) { - // ArrayDimensions == std::vector - auto dims = matlab_array.getDimensions(); - // T* ptr = matlab_array.release().get(); - // // mat(ptr_aux_mem, n_rows, n_cols, copy_aux_mem = true, strict = false) - // arma::Mat mat(ptr, dims[0], dims[1]); //, false); - - // TODO(mfbolus): for some reason, using the above pointer at times leads to - // getting garbage values. matlab array values may be stored in non-contiguous - // memory? - // - // armadillo and matlab both use column-major ordering, so this should work: - size_t n_elem = dims[0] * dims[1]; - arma::Mat mat(dims[0], dims[1], arma::fill::zeros); - size_t k(0); - for (auto m: matlab_array) { - mat[k] = m; - k++; - } - return mat; -}; - -template -matlab::data::TypedArray a2m_mat(const arma::Mat& arma_mat, - matlab::data::ArrayFactory& factory) { - const matlab::data::TypedArray matlab_mat = factory.createArray( - {arma_mat.n_rows, arma_mat.n_cols}, arma_mat.memptr(), - arma_mat.memptr() + arma_mat.n_elem); - return matlab_mat; -}; - -template -matlab::data::TypedArray a2m_vec(const arma::Col& arma_vec, - matlab::data::ArrayFactory& factory) { - const matlab::data::TypedArray matlab_mat = - factory.createArray({arma_vec.n_elem, 1}, arma_vec.memptr(), - arma_vec.memptr() + arma_vec.n_elem); - return matlab_mat; -}; - -template -matlab::data::TypedArray s2m_vec(const std::vector& std_vec, - matlab::data::ArrayFactory& factory) { - const matlab::data::TypedArray matlab_mat = factory.createArray( - {std_vec.size(), 1}, std_vec.data(), std_vec.data() + std_vec.size()); - return matlab_mat; -}; -} // namespace armamexcpp - -#endif -``` - - -------------------------------- - -Updated on 19 May 2022 at 17:16:05 Eastern Daylight Time +--- +title: ldsCtrlEst_h/mex_cpp_util.h +summary: arma <-> mex interoperability utilities (Matlab C++ API) + +--- + +# ldsCtrlEst_h/mex_cpp_util.h + +arma <-> mex interoperability utilities (Matlab C++ API) [More...](#detailed-description) + + + +## Namespaces + +| Name | +| -------------- | +| **[armamexcpp](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/)**
arma/mex interface using Matlab C++ API | + +## Detailed Description + + + +This file defines utility functions for interoperability between armadillo and Matlab's C++ mex API. + + + + + +## Source code + +```cpp +//===-- ldsCtrlEst_h/mex_cpp_util.h - Mex C++ API Utilities -----*- C++ -*-===// +// +// Copyright 2021 Michael Bolus +// Copyright 2021 Georgia Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// + +#ifndef LDSCTRLEST_MEXCPP_UTIL_H +#define LDSCTRLEST_MEXCPP_UTIL_H + +#include + +#include "mex.hpp" +#include "mexAdapter.hpp" + +namespace armamexcpp { +template +std::vector> m2a_cellmat(matlab::data::CellArray& matlab_cell) { + size_t n_cells = matlab_cell.getNumberOfElements(); + std::vector> arma_mat(n_cells, + arma::Mat(1, 1, arma::fill::zeros)); + for (size_t k = 0; k < n_cells; k++) { + matlab::data::TypedArray matlab_mat = matlab_cell[k]; + auto dims = matlab_mat.getDimensions(); + arma_mat[k] = arma::Mat(matlab_mat.release().get(), dims[0], dims[1]); + } + return arma_mat; +}; + +template +std::vector m2s_vec(matlab::data::TypedArray& matlab_array) { + size_t n_elem = matlab_array.getNumberOfElements(); + T* ptr = matlab_array.release().get(); + std::vector vec(ptr, ptr + n_elem); + return vec; +}; + +template +arma::Col m2a_vec(matlab::data::TypedArray matlab_array) { + size_t n_elem = matlab_array.getNumberOfElements(); + // T* ptr = matlab_array.release().get(); + // arma::Col vec(ptr, n_elem); //, false); + // TODO(mfbolus): for some reason, using the above pointer at times leads to + // getting garbage values. matlab array values may be stored in non-contiguous + // memory? + arma::Col vec(n_elem, arma::fill::zeros); + for (size_t k = 0; k < n_elem; k++) { + vec[k] = matlab_array[k]; + } + return vec; +}; + +template +arma::Mat m2a_mat(matlab::data::TypedArray matlab_array) { + // ArrayDimensions == std::vector + auto dims = matlab_array.getDimensions(); + // T* ptr = matlab_array.release().get(); + // // mat(ptr_aux_mem, n_rows, n_cols, copy_aux_mem = true, strict = false) + // arma::Mat mat(ptr, dims[0], dims[1]); //, false); + + // TODO(mfbolus): for some reason, using the above pointer at times leads to + // getting garbage values. matlab array values may be stored in non-contiguous + // memory? + // + // armadillo and matlab both use column-major ordering, so this should work: + size_t n_elem = dims[0] * dims[1]; + arma::Mat mat(dims[0], dims[1], arma::fill::zeros); + size_t k(0); + for (auto m: matlab_array) { + mat[k] = m; + k++; + } + return mat; +}; + +template +matlab::data::TypedArray a2m_mat(const arma::Mat& arma_mat, + matlab::data::ArrayFactory& factory) { + const matlab::data::TypedArray matlab_mat = factory.createArray( + {arma_mat.n_rows, arma_mat.n_cols}, arma_mat.memptr(), + arma_mat.memptr() + arma_mat.n_elem); + return matlab_mat; +}; + +template +matlab::data::TypedArray a2m_vec(const arma::Col& arma_vec, + matlab::data::ArrayFactory& factory) { + const matlab::data::TypedArray matlab_mat = + factory.createArray({arma_vec.n_elem, 1}, arma_vec.memptr(), + arma_vec.memptr() + arma_vec.n_elem); + return matlab_mat; +}; + +template +matlab::data::TypedArray s2m_vec(const std::vector& std_vec, + matlab::data::ArrayFactory& factory) { + const matlab::data::TypedArray matlab_mat = factory.createArray( + {std_vec.size(), 1}, std_vec.data(), std_vec.data() + std_vec.size()); + return matlab_mat; +}; +} // namespace armamexcpp + +#endif +``` + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Modules/_index.md b/misc/docs-hugo/content/docs/api/Modules/_index.md index a4bc6ccf..ce773aa8 100644 --- a/misc/docs-hugo/content/docs/api/Modules/_index.md +++ b/misc/docs-hugo/content/docs/api/Modules/_index.md @@ -1,28 +1,28 @@ ---- -title: Modules - ---- - -# Modules - - - - - - - -- **[Control Mode Bit Masks](/lds-ctrl-est/docs/api/modules/group__control__masks/)**
provides fill types for constructing new armadillo vectors, matrices - - - - - -- **[Defaults](/lds-ctrl-est/docs/api/modules/group__defaults/)** - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:06 Eastern Daylight Time +--- +title: Modules + +--- + +# Modules + + + + + + + +- **[Control Mode Bit Masks](/lds-ctrl-est/docs/api/modules/group__control__masks/)**
provides fill types for constructing new armadillo vectors, matrices + + + + + +- **[Defaults](/lds-ctrl-est/docs/api/modules/group__defaults/)** + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Modules/group__control__masks.md b/misc/docs-hugo/content/docs/api/Modules/group__control__masks.md index 972b05de..8530e1d1 100644 --- a/misc/docs-hugo/content/docs/api/Modules/group__control__masks.md +++ b/misc/docs-hugo/content/docs/api/Modules/group__control__masks.md @@ -1,70 +1,70 @@ ---- -title: Control Mode Bit Masks -summary: provides fill types for constructing new armadillo vectors, matrices - ---- - -# Control Mode Bit Masks - -provides fill types for constructing new armadillo vectors, matrices

[More...](#detailed-description) -
- - -## Attributes - -| | Name | -| -------------- | -------------- | -| const std::size_t | **[kControlTypeDeltaU](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypedeltau)**
control designed to penalize change in input | -| const std::size_t | **[kControlTypeIntY](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypeinty)**
control using integral action | -| const std::size_t | **[kControlTypeAdaptM](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypeadaptm)**
adapt control setpoint with re-estimated disturbance `m` | - -## Detailed Description - - - -Control mode bit masks. These can be bit-wise OR'd to use in combination. - - - -## Attribute Details - -### kControlTypeDeltaU - -```cpp -static const std::size_t kControlTypeDeltaU = 0x1; -``` - - - -Control was designed to penalize change in input (i.e., the state was augmented with input `u`) - - -### kControlTypeIntY - -```cpp -static const std::size_t kControlTypeIntY = kControlTypeDeltaU << 1; -``` - - - -Control using integral action (i.e., the state was augmented with output `y` during design) - - -### kControlTypeAdaptM - -```cpp -static const std::size_t kControlTypeAdaptM = kControlTypeDeltaU << 2; -``` - - - -Adapt control setpoint adapted with re-estimated process disturbance `m`. - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:04 Eastern Daylight Time +--- +title: Control Mode Bit Masks +summary: provides fill types for constructing new armadillo vectors, matrices + +--- + +# Control Mode Bit Masks + +provides fill types for constructing new armadillo vectors, matrices

[More...](#detailed-description) +
+ + +## Attributes + +| | Name | +| -------------- | -------------- | +| const std::size_t | **[kControlTypeDeltaU](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypedeltau)**
control designed to penalize change in input | +| const std::size_t | **[kControlTypeIntY](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypeinty)**
control using integral action | +| const std::size_t | **[kControlTypeAdaptM](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypeadaptm)**
adapt control setpoint with re-estimated disturbance `m` | + +## Detailed Description + + + +Control mode bit masks. These can be bit-wise OR'd to use in combination. + + + +## Attribute Details + +### kControlTypeDeltaU + +```cpp +static const std::size_t kControlTypeDeltaU = 0x1; +``` + + + +Control was designed to penalize change in input (i.e., the state was augmented with input `u`) + + +### kControlTypeIntY + +```cpp +static const std::size_t kControlTypeIntY = kControlTypeDeltaU << 1; +``` + + + +Control using integral action (i.e., the state was augmented with output `y` during design) + + +### kControlTypeAdaptM + +```cpp +static const std::size_t kControlTypeAdaptM = kControlTypeDeltaU << 2; +``` + + + +Adapt control setpoint adapted with re-estimated process disturbance `m`. + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Modules/group__defaults.md b/misc/docs-hugo/content/docs/api/Modules/group__defaults.md index 4f744568..ee90cde0 100644 --- a/misc/docs-hugo/content/docs/api/Modules/group__defaults.md +++ b/misc/docs-hugo/content/docs/api/Modules/group__defaults.md @@ -1,60 +1,60 @@ ---- -title: Defaults - ---- - -# Defaults - -

[More...](#detailed-description) -
- - -## Attributes - -| | Name | -| -------------- | -------------- | -| const data_t | **[kDefaultP0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultp0)**
default state estimate covar | -| const data_t | **[kDefaultQ0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultq0)**
default process noise covar | -| const data_t | **[kDefaultR0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultr0)**
default output noise covar | - -## Detailed Description - - - -Default values for common variables (e.g., default diagonal elements of covariances) - - - -## Attribute Details - -### kDefaultP0 - -```cpp -static const data_t kDefaultP0 = 1e-6; -``` - - - -### kDefaultQ0 - -```cpp -static const data_t kDefaultQ0 = 1e-6; -``` - - - -### kDefaultR0 - -```cpp -static const data_t kDefaultR0 = 1e-2; -``` - - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:04 Eastern Daylight Time +--- +title: Defaults + +--- + +# Defaults + +

[More...](#detailed-description) +
+ + +## Attributes + +| | Name | +| -------------- | -------------- | +| const data_t | **[kDefaultP0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultp0)**
default state estimate covar | +| const data_t | **[kDefaultQ0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultq0)**
default process noise covar | +| const data_t | **[kDefaultR0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultr0)**
default output noise covar | + +## Detailed Description + + + +Default values for common variables (e.g., default diagonal elements of covariances) + + + +## Attribute Details + +### kDefaultP0 + +```cpp +static const data_t kDefaultP0 = 1e-6; +``` + + + +### kDefaultQ0 + +```cpp +static const data_t kDefaultQ0 = 1e-6; +``` + + + +### kDefaultR0 + +```cpp +static const data_t kDefaultR0 = 1e-2; +``` + + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Namespaces/_index.md b/misc/docs-hugo/content/docs/api/Namespaces/_index.md index 0ff4e7f6..ad5aa7ed 100644 --- a/misc/docs-hugo/content/docs/api/Namespaces/_index.md +++ b/misc/docs-hugo/content/docs/api/Namespaces/_index.md @@ -1,38 +1,42 @@ ---- -title: Namespaces - ---- - -# Namespaces - - - - - - -- **[armamexc](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/)**
arma/mex interface using Matlab C API - - - -- **[armamexcpp](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/)**
arma/mex interface using Matlab C++ API - - - - - - -- **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. - - - -- **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. - - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:06 Eastern Daylight Time +--- +title: Namespaces + +--- + +# Namespaces + + + + + + +- **[armamexc](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/)**
arma/mex interface using Matlab C API + + + +- **[armamexcpp](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/)**
arma/mex interface using Matlab C++ API + + + + + + +- **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. + + + +- **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. + + + + + + +- **[std](/lds-ctrl-est/docs/api/namespaces/namespacestd/)** + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Namespaces/namespacearmamexc.md b/misc/docs-hugo/content/docs/api/Namespaces/namespacearmamexc.md index fb69bd3e..6b4f6d9d 100644 --- a/misc/docs-hugo/content/docs/api/Namespaces/namespacearmamexc.md +++ b/misc/docs-hugo/content/docs/api/Namespaces/namespacearmamexc.md @@ -1,124 +1,124 @@ ---- -title: armamexc -summary: arma/mex interface using Matlab C API - ---- - -# armamexc - -arma/mex interface using Matlab C API

[More...](#detailed-description) -
- - -## Functions - -| | Name | -| -------------- | -------------- | -| template
auto | **[m2T_scalar](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/#function-m2t-scalar)**(const mxArray * matlab_scalar)
Convert Matlab mxArray to scalar of type T. | -| template
auto | **[m2a_mat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/#function-m2a-mat)**(const mxArray * matlab_mat, bool copy_aux_mem =false, bool strict =true)
Convert matlab matrix to armadillo. | -| template
auto | **[a2m_mat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/#function-a2m-mat)**(arma::Mat< T > const & arma_mat)
Convert armadillo to matlab matrix. | -| template
auto | **[a2m_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/#function-a2m-vec)**(arma::Col< T > const & arma_vec)
Convert armadillo to matlab vector. | - -## Detailed Description - - - -Utilities for arma/mex interface _using Matlab C API_ - - -## Function Details - -### m2T_scalar - -```cpp -template -inline auto m2T_scalar( - const mxArray * matlab_scalar -) -``` - - - -**Parameters**: - - * **matlab_scalar** matlab scalar - - -**Template Parameters**: - - * **T** type - - -**Return**: scalar of type T - -### m2a_mat - -```cpp -template -inline auto m2a_mat( - const mxArray * matlab_mat, - bool copy_aux_mem =false, - bool strict =true -) -``` - - - -**Parameters**: - - * **matlab_mat** matlab matrix - * **copy_aux_mem** [optional] whether to copy auxiliary memory - * **strict** [optional] strictly enforce the above - - -**Template Parameters**: - - * **T** type - - -**Return**: armadillo matrix of type T - -### a2m_mat - -```cpp -template -inline auto a2m_mat( - arma::Mat< T > const & arma_mat -) -``` - - - -**Parameters**: - - * **arma_mat** armadillo matrix - - -**Return**: matlab matrix - -### a2m_vec - -```cpp -template -inline auto a2m_vec( - arma::Col< T > const & arma_vec -) -``` - - - -**Parameters**: - - * **arma_vec** armadillo vector - - -**Return**: matlab vector - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:03 Eastern Daylight Time +--- +title: armamexc +summary: arma/mex interface using Matlab C API + +--- + +# armamexc + +arma/mex interface using Matlab C API

[More...](#detailed-description) +
+ + +## Functions + +| | Name | +| -------------- | -------------- | +| template
T | **[m2T_scalar](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/#function-m2t-scalar)**(const mxArray * matlab_scalar)
Convert Matlab mxArray to scalar of type T. | +| template
arma::Mat< T > | **[m2a_mat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/#function-m2a-mat)**(const mxArray * matlab_mat, bool copy_aux_mem =false, bool strict =true)
Convert matlab matrix to armadillo. | +| template
mxArray * | **[a2m_mat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/#function-a2m-mat)**(arma::Mat< T > const & arma_mat)
Convert armadillo to matlab matrix. | +| template
mxArray * | **[a2m_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexc/#function-a2m-vec)**(arma::Col< T > const & arma_vec)
Convert armadillo to matlab vector. | + +## Detailed Description + + + +Utilities for arma/mex interface _using Matlab C API_ + + +## Function Details + +### m2T_scalar + +```cpp +template +inline T m2T_scalar( + const mxArray * matlab_scalar +) +``` + + + +**Parameters**: + + * **matlab_scalar** matlab scalar + + +**Template Parameters**: + + * **T** type + + +**Return**: scalar of type T + +### m2a_mat + +```cpp +template +inline arma::Mat< T > m2a_mat( + const mxArray * matlab_mat, + bool copy_aux_mem =false, + bool strict =true +) +``` + + + +**Parameters**: + + * **matlab_mat** matlab matrix + * **copy_aux_mem** [optional] whether to copy auxiliary memory + * **strict** [optional] strictly enforce the above + + +**Template Parameters**: + + * **T** type + + +**Return**: armadillo matrix of type T + +### a2m_mat + +```cpp +template +inline mxArray * a2m_mat( + arma::Mat< T > const & arma_mat +) +``` + + + +**Parameters**: + + * **arma_mat** armadillo matrix + + +**Return**: matlab matrix + +### a2m_vec + +```cpp +template +inline mxArray * a2m_vec( + arma::Col< T > const & arma_vec +) +``` + + + +**Parameters**: + + * **arma_vec** armadillo vector + + +**Return**: matlab vector + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:29 EDT diff --git a/misc/docs-hugo/content/docs/api/Namespaces/namespacearmamexcpp.md b/misc/docs-hugo/content/docs/api/Namespaces/namespacearmamexcpp.md index e160ecf4..cf0e0756 100644 --- a/misc/docs-hugo/content/docs/api/Namespaces/namespacearmamexcpp.md +++ b/misc/docs-hugo/content/docs/api/Namespaces/namespacearmamexcpp.md @@ -1,208 +1,208 @@ ---- -title: armamexcpp -summary: arma/mex interface using Matlab C++ API - ---- - -# armamexcpp - -arma/mex interface using Matlab C++ API

[More...](#detailed-description) -
- - -## Functions - -| | Name | -| -------------- | -------------- | -| template
std::vector< arma::Mat< T > > | **[m2a_cellmat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-m2a-cellmat)**(matlab::data::CellArray & matlab_cell)
Convert matlab cell array to vector of armadillo matrices. | -| template
std::vector< T > | **[m2s_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-m2s-vec)**(matlab::data::TypedArray< T > & matlab_array)
Convert matlab matrix to a vector of scalars. | -| template
arma::Col< T > | **[m2a_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-m2a-vec)**(matlab::data::TypedArray< T > matlab_array)
Convert matlab to armadillo vector. | -| template
arma::Mat< T > | **[m2a_mat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-m2a-mat)**(matlab::data::TypedArray< T > matlab_array)
Convert matlab to armadillo matrix. | -| template
matlab::data::TypedArray< T > | **[a2m_mat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-a2m-mat)**(const arma::Mat< T > & arma_mat, matlab::data::ArrayFactory & factory)
Convert armadillo to matlab matrix. | -| template
matlab::data::TypedArray< T > | **[a2m_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-a2m-vec)**(const arma::Col< T > & arma_vec, matlab::data::ArrayFactory & factory)
Convert armadillo to matlab vector. | -| template
matlab::data::TypedArray< T > | **[s2m_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-s2m-vec)**(const std::vector< T > & std_vec, matlab::data::ArrayFactory & factory)
Convert vector of scalar T to matlab matrix. | - -## Detailed Description - - - -utilities for arma/mex interface _using Matlab C++ API_ - - -## Function Details - -### m2a_cellmat - -```cpp -template -std::vector< arma::Mat< T > > m2a_cellmat( - matlab::data::CellArray & matlab_cell -) -``` - - - -**Parameters**: - - * **matlab_cell** matlab cell - - -**Template Parameters**: - - * **T** type - - -**Return**: vector of armadillo matrices of type T - -### m2s_vec - -```cpp -template -std::vector< T > m2s_vec( - matlab::data::TypedArray< T > & matlab_array -) -``` - - - -**Parameters**: - - * **matlab_array** matlab array - - -**Template Parameters**: - - * **T** type - - -**Return**: vector of type T - -### m2a_vec - -```cpp -template -arma::Col< T > m2a_vec( - matlab::data::TypedArray< T > matlab_array -) -``` - - - -**Parameters**: - - * **matlab_array** matlab array - - -**Template Parameters**: - - * **T** type - - -**Return**: armadillo vector of type T - -### m2a_mat - -```cpp -template -arma::Mat< T > m2a_mat( - matlab::data::TypedArray< T > matlab_array -) -``` - - - -**Parameters**: - - * **matlab_array** matlab matrix - - -**Template Parameters**: - - * **T** type - - -**Return**: armadillo matrix of type T - -### a2m_mat - -```cpp -template -matlab::data::TypedArray< T > a2m_mat( - const arma::Mat< T > & arma_mat, - matlab::data::ArrayFactory & factory -) -``` - - - -**Parameters**: - - * **arma_mat** arma matrix - * **factory** matlab "array factory" - - -**Template Parameters**: - - * **T** type - - -**Return**: matlab matrix - -### a2m_vec - -```cpp -template -matlab::data::TypedArray< T > a2m_vec( - const arma::Col< T > & arma_vec, - matlab::data::ArrayFactory & factory -) -``` - - - -**Parameters**: - - * **arma_vec** armadillo vector - * **factory** matlab "array factory" - - -**Template Parameters**: - - * **T** type - - -**Return**: matlab matrix - -### s2m_vec - -```cpp -template -matlab::data::TypedArray< T > s2m_vec( - const std::vector< T > & std_vec, - matlab::data::ArrayFactory & factory -) -``` - - - -**Parameters**: - - * **std_vec** standard vector - * **factory** matlab "array factory" - - -**Template Parameters**: - - * **T** type - - -**Return**: matlab matrix - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:03 Eastern Daylight Time +--- +title: armamexcpp +summary: arma/mex interface using Matlab C++ API + +--- + +# armamexcpp + +arma/mex interface using Matlab C++ API

[More...](#detailed-description) +
+ + +## Functions + +| | Name | +| -------------- | -------------- | +| template
std::vector< arma::Mat< T > > | **[m2a_cellmat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-m2a-cellmat)**(matlab::data::CellArray & matlab_cell)
Convert matlab cell array to vector of armadillo matrices. | +| template
std::vector< T > | **[m2s_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-m2s-vec)**(matlab::data::TypedArray< T > & matlab_array)
Convert matlab matrix to a vector of scalars. | +| template
arma::Col< T > | **[m2a_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-m2a-vec)**(matlab::data::TypedArray< T > matlab_array)
Convert matlab to armadillo vector. | +| template
arma::Mat< T > | **[m2a_mat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-m2a-mat)**(matlab::data::TypedArray< T > matlab_array)
Convert matlab to armadillo matrix. | +| template
matlab::data::TypedArray< T > | **[a2m_mat](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-a2m-mat)**(const arma::Mat< T > & arma_mat, matlab::data::ArrayFactory & factory)
Convert armadillo to matlab matrix. | +| template
matlab::data::TypedArray< T > | **[a2m_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-a2m-vec)**(const arma::Col< T > & arma_vec, matlab::data::ArrayFactory & factory)
Convert armadillo to matlab vector. | +| template
matlab::data::TypedArray< T > | **[s2m_vec](/lds-ctrl-est/docs/api/namespaces/namespacearmamexcpp/#function-s2m-vec)**(const std::vector< T > & std_vec, matlab::data::ArrayFactory & factory)
Convert vector of scalar T to matlab matrix. | + +## Detailed Description + + + +utilities for arma/mex interface _using Matlab C++ API_ + + +## Function Details + +### m2a_cellmat + +```cpp +template +std::vector< arma::Mat< T > > m2a_cellmat( + matlab::data::CellArray & matlab_cell +) +``` + + + +**Parameters**: + + * **matlab_cell** matlab cell + + +**Template Parameters**: + + * **T** type + + +**Return**: vector of armadillo matrices of type T + +### m2s_vec + +```cpp +template +std::vector< T > m2s_vec( + matlab::data::TypedArray< T > & matlab_array +) +``` + + + +**Parameters**: + + * **matlab_array** matlab array + + +**Template Parameters**: + + * **T** type + + +**Return**: vector of type T + +### m2a_vec + +```cpp +template +arma::Col< T > m2a_vec( + matlab::data::TypedArray< T > matlab_array +) +``` + + + +**Parameters**: + + * **matlab_array** matlab array + + +**Template Parameters**: + + * **T** type + + +**Return**: armadillo vector of type T + +### m2a_mat + +```cpp +template +arma::Mat< T > m2a_mat( + matlab::data::TypedArray< T > matlab_array +) +``` + + + +**Parameters**: + + * **matlab_array** matlab matrix + + +**Template Parameters**: + + * **T** type + + +**Return**: armadillo matrix of type T + +### a2m_mat + +```cpp +template +matlab::data::TypedArray< T > a2m_mat( + const arma::Mat< T > & arma_mat, + matlab::data::ArrayFactory & factory +) +``` + + + +**Parameters**: + + * **arma_mat** arma matrix + * **factory** matlab "array factory" + + +**Template Parameters**: + + * **T** type + + +**Return**: matlab matrix + +### a2m_vec + +```cpp +template +matlab::data::TypedArray< T > a2m_vec( + const arma::Col< T > & arma_vec, + matlab::data::ArrayFactory & factory +) +``` + + + +**Parameters**: + + * **arma_vec** armadillo vector + * **factory** matlab "array factory" + + +**Template Parameters**: + + * **T** type + + +**Return**: matlab matrix + +### s2m_vec + +```cpp +template +matlab::data::TypedArray< T > s2m_vec( + const std::vector< T > & std_vec, + matlab::data::ArrayFactory & factory +) +``` + + + +**Parameters**: + + * **std_vec** standard vector + * **factory** matlab "array factory" + + +**Template Parameters**: + + * **T** type + + +**Return**: matlab matrix + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:29 EDT diff --git a/misc/docs-hugo/content/docs/api/Namespaces/namespacelds.md b/misc/docs-hugo/content/docs/api/Namespaces/namespacelds.md index f10de3ef..295e7263 100644 --- a/misc/docs-hugo/content/docs/api/Namespaces/namespacelds.md +++ b/misc/docs-hugo/content/docs/api/Namespaces/namespacelds.md @@ -1,376 +1,313 @@ ---- -title: lds -summary: Linear Dynamical Systems (LDS) namespace. - ---- - -# lds - -Linear Dynamical Systems (LDS) namespace.
- -## Namespaces - -| Name | -| -------------- | -| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | -| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | - -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1controller/)** | -| class | **[lds::EM](/lds-ctrl-est/docs/api/classes/classlds_1_1em/)** | -| class | **[lds::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1fit/)**
LDS [Fit]() Type. | -| class | **[lds::SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1ssid/)** | -| class | **[lds::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1switchedcontroller/)**
[SwitchedController]() Type. | -| class | **[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1system/)**
Linear Dynamical [System]() Type. | -| class | **[lds::UniformMatrixList](/lds-ctrl-est/docs/api/classes/classlds_1_1uniformmatrixlist/)** | -| class | **[lds::UniformSystemList](/lds-ctrl-est/docs/api/classes/classlds_1_1uniformsystemlist/)** | -| class | **[lds::UniformVectorList](/lds-ctrl-est/docs/api/classes/classlds_1_1uniformvectorlist/)** | - -## Types - -| | Name | -| -------------- | -------------- | -| enum| **[SSIDWt](/lds-ctrl-est/docs/api/namespaces/namespacelds/#enum-ssidwt)** { kSSIDNone, kSSIDMOESP, kSSIDCVA}
weighting options for [SSID]() | -| enum| **[MatrixListFreeDim](/lds-ctrl-est/docs/api/namespaces/namespacelds/#enum-matrixlistfreedim)** { kMatFreeDimNone, kMatFreeDim1, kMatFreeDim2} | -| using double | **[data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t)** | -| using arma::Col< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > | **[Vector](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-vector)** | -| using arma::Mat< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > | **[Matrix](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-matrix)** | -| using arma::Cube< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > | **[Cube](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-cube)** | -| using arma::subview< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > | **[View](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-view)** | - -## Functions - -| | Name | -| -------------- | -------------- | -| void | **[Limit](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-limit)**(std::vector< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > & x, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) lb, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) ub) | -| void | **[Limit](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-limit)**(Vector & x, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) lb, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) ub) | -| void | **[Limit](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-limit)**(Matrix & x, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) lb, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) ub) | -| void | **[Reassign](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-reassign)**(Vector & some, const Vector & other, const std::string & parenthetical ="Reassign")
reassigns contents of some Vector in place | -| void | **[Reassign](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-reassign)**(Matrix & some, const Matrix & other, const std::string & parenthetical ="Reassign")
reassigns contents of some Matrix in place | -| void | **[ForceSymPD](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-forcesympd)**(Matrix & X)
forces matrix to be symmetric positive-definite | -| void | **[ForceSymMinEig](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-forcesymmineig)**(Matrix & X, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) eig_min =0)
forces matrix to be symmetric and have a minimum eigenvalue | -| void | **[lq](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-lq)**(Matrix & L, Matrix & Qt, const Matrix & X)
LQ decomposition. | -| Matrix | **[calcCov](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-calccov)**(const Matrix & A, const Matrix & B)
Calculate covariance matrix. | - -## Attributes - -| | Name | -| -------------- | -------------- | -| const std::size_t | **[kControlTypeDeltaU](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypedeltau)**
control designed to penalize change in input | -| const std::size_t | **[kControlTypeIntY](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypeinty)**
control using integral action | -| const std::size_t | **[kControlTypeAdaptM](/lds-ctrl-est/docs/api/modules/group__control__masks/#variable-kcontroltypeadaptm)**
adapt control setpoint with re-estimated disturbance `m` | -| const [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) | **[kInf](/lds-ctrl-est/docs/api/namespaces/namespacelds/#variable-kinf)**
Some useful numbers. | -| const [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) | **[kPi](/lds-ctrl-est/docs/api/namespaces/namespacelds/#variable-kpi)** | -| const [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) | **[kDefaultP0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultp0)**
default state estimate covar | -| const [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) | **[kDefaultQ0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultq0)**
default process noise covar | -| const [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) | **[kDefaultR0](/lds-ctrl-est/docs/api/modules/group__defaults/#variable-kdefaultr0)**
default output noise covar | - -## Type Details - -### SSIDWt - -| Enumerator | Value | Description | -| ---------- | ----- | ----------- | -| kSSIDNone | | None. | -| kSSIDMOESP | | MOESP (AKA "robust method" in van Overschee 1996) | -| kSSIDCVA | | CVA "Canonical Variate Analysis". | - - - - - -Weighting options for singular value decomposition performed during subspace identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1ssid/)) - -Reference: - -van Overschee, de Moor. 1996. Subspace Identification for Linear Systems. - - -### MatrixListFreeDim - -| Enumerator | Value | Description | -| ---------- | ----- | ----------- | -| kMatFreeDimNone | | neither dim free to be hetero in mat list | -| kMatFreeDim1 | | allow 1st dim of mats in list to be hetero | -| kMatFreeDim2 | | allow 2nd dim of mats in list to be hetero | - - - - - -### data_t - -```cpp -using lds::data_t = typedef double; -``` - - - -Type of all data in library. If need 32b, change `double` to `float`. This could be potentially useful for large scale problems where there are memory constraints. - - -### Vector - -```cpp -using lds::Vector = typedef arma::Col; -``` - - - -### Matrix - -```cpp -using lds::Matrix = typedef arma::Mat; -``` - - - -### Cube - -```cpp -using lds::Cube = typedef arma::Cube; -``` - - - -### View - -```cpp -using lds::View = typedef arma::subview; -``` - - - - -## Function Details - -### Limit - -```cpp -inline void Limit( - std::vector< data_t > & x, - data_t lb, - data_t ub -) -``` - - - -### Limit - -```cpp -inline void Limit( - Vector & x, - data_t lb, - data_t ub -) -``` - - - -### Limit - -```cpp -inline void Limit( - Matrix & x, - data_t lb, - data_t ub -) -``` - - - -### Reassign - -```cpp -inline void Reassign( - Vector & some, - const Vector & other, - const std::string & parenthetical ="Reassign" -) -``` - - - -**Parameters**: - - * **some** some Vector - * **other** other Vector - * **parenthetical** optional description provided by caller to ease debugging - - -### Reassign - -```cpp -inline void Reassign( - Matrix & some, - const Matrix & other, - const std::string & parenthetical ="Reassign" -) -``` - - - -**Parameters**: - - * **some** some Matrix - * **other** other Matrix - * **parenthetical** optional description provided by caller to ease debugging - - -### ForceSymPD - -```cpp -void ForceSymPD( - Matrix & X -) -``` - - - -**Parameters**: - - * **X** mutated matrix - - -### ForceSymMinEig - -```cpp -void ForceSymMinEig( - Matrix & X, - data_t eig_min =0 -) -``` - - - -**Parameters**: - - * **X** mutated matrix - * **eig_min** [optional] minimum eigen value - - -### lq - -```cpp -void lq( - Matrix & L, - Matrix & Qt, - const Matrix & X -) -``` - - - -**Parameters**: - - * **L** lower triangle matrix - * **Qt** orthonormal matrix (transposed cf QR decomp) - * **X** matrix being decomposed - - -### calcCov - -```cpp -Matrix calcCov( - const Matrix & A, - const Matrix & B -) -``` - - - -**Parameters**: - - * **A** some matrix - * **B** some other matrix - - -**Return**: covariance - - -## Attribute Details - -### kControlTypeDeltaU - -```cpp -static const std::size_t kControlTypeDeltaU = 0x1; -``` - - - -Control was designed to penalize change in input (i.e., the state was augmented with input `u`) - - -### kControlTypeIntY - -```cpp -static const std::size_t kControlTypeIntY = kControlTypeDeltaU << 1; -``` - - - -Control using integral action (i.e., the state was augmented with output `y` during design) - - -### kControlTypeAdaptM - -```cpp -static const std::size_t kControlTypeAdaptM = kControlTypeDeltaU << 2; -``` - - - -Adapt control setpoint adapted with re-estimated process disturbance `m`. - - -### kInf - -```cpp -static const data_t kInf = std::numeric_limits::infinity(); -``` - - - -### kPi - -```cpp -static const data_t kPi = arma::datum::pi; -``` - - - -### kDefaultP0 - -```cpp -static const data_t kDefaultP0 = 1e-6; -``` - - - -### kDefaultQ0 - -```cpp -static const data_t kDefaultQ0 = 1e-6; -``` - - - -### kDefaultR0 - -```cpp -static const data_t kDefaultR0 = 1e-2; -``` - - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:03 Eastern Daylight Time +--- +title: lds +summary: Linear Dynamical Systems (LDS) namespace. + +--- + +# lds + +Linear Dynamical Systems (LDS) namespace.
+ +## Namespaces + +| Name | +| -------------- | +| **[lds::gaussian](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1gaussian/)**
Linear Dynamical Systems with Gaussian observations. | +| **[lds::poisson](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/)**
Linear Dynamical Systems with Poisson observations. | + +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1_controller/)** | +| class | **[lds::EM](/lds-ctrl-est/docs/api/classes/classlds_1_1_e_m/)** | +| class | **[lds::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1_fit/)**
LDS [Fit]() Type. | +| class | **[lds::SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1_s_s_i_d/)** | +| class | **[lds::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1_switched_controller/)**
[SwitchedController]() Type. | +| class | **[lds::System](/lds-ctrl-est/docs/api/classes/classlds_1_1_system/)**
Linear Dynamical [System]() Type. | +| class | **[lds::UniformMatrixList](/lds-ctrl-est/docs/api/classes/classlds_1_1_uniform_matrix_list/)** | +| class | **[lds::UniformSystemList](/lds-ctrl-est/docs/api/classes/classlds_1_1_uniform_system_list/)** | +| class | **[lds::UniformVectorList](/lds-ctrl-est/docs/api/classes/classlds_1_1_uniform_vector_list/)** | + +## Types + +| | Name | +| -------------- | -------------- | +| enum| **[SSIDWt](/lds-ctrl-est/docs/api/namespaces/namespacelds/#enum-ssidwt)** { kSSIDNone, kSSIDMOESP, kSSIDCVA}
weighting options for [SSID]() | +| enum| **[MatrixListFreeDim](/lds-ctrl-est/docs/api/namespaces/namespacelds/#enum-matrixlistfreedim)** { kMatFreeDimNone, kMatFreeDim1, kMatFreeDim2} | +| using double | **[data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t)** | +| using arma::Col< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > | **[Vector](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-vector)** | +| using arma::Mat< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > | **[Matrix](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-matrix)** | +| using arma::Cube< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > | **[Cube](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-cube)** | +| using arma::subview< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > | **[View](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-view)** | + +## Functions + +| | Name | +| -------------- | -------------- | +| void | **[Limit](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-limit)**(std::vector< [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) > & x, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) lb, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) ub) | +| void | **[Limit](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-limit)**(Vector & x, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) lb, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) ub) | +| void | **[Limit](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-limit)**(Matrix & x, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) lb, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) ub) | +| void | **[Reassign](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-reassign)**(Vector & some, const Vector & other, const std::string & parenthetical ="Reassign")
reassigns contents of some Vector in place | +| void | **[Reassign](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-reassign)**(Matrix & some, const Matrix & other, const std::string & parenthetical ="Reassign")
reassigns contents of some Matrix in place | +| void | **[ForceSymPD](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-forcesympd)**(Matrix & X)
forces matrix to be symmetric positive-definite | +| void | **[ForceSymMinEig](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-forcesymmineig)**(Matrix & X, [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) eig_min =0)
forces matrix to be symmetric and have a minimum eigenvalue | +| void | **[lq](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-lq)**(Matrix & L, Matrix & Qt, const Matrix & X)
LQ decomposition. | +| Matrix | **[calcCov](/lds-ctrl-est/docs/api/namespaces/namespacelds/#function-calccov)**(const Matrix & A, const Matrix & B)
Calculate covariance matrix. | + +## Attributes + +| | Name | +| -------------- | -------------- | +| const [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) | **[kInf](/lds-ctrl-est/docs/api/namespaces/namespacelds/#variable-kinf)**
Some useful numbers. | +| const [data_t](/lds-ctrl-est/docs/api/namespaces/namespacelds/#using-data-t) | **[kPi](/lds-ctrl-est/docs/api/namespaces/namespacelds/#variable-kpi)** | + +## Type Details + +### SSIDWt + +| Enumerator | Value | Description | +| ---------- | ----- | ----------- | +| kSSIDNone | | None. | +| kSSIDMOESP | | MOESP (AKA "robust method" in van Overschee 1996) | +| kSSIDCVA | | CVA "Canonical Variate Analysis". | + + + + + +Weighting options for singular value decomposition performed during subspace identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1_s_s_i_d/)) + +Reference: + +van Overschee, de Moor. 1996. Subspace Identification for Linear Systems. + + +### MatrixListFreeDim + +| Enumerator | Value | Description | +| ---------- | ----- | ----------- | +| kMatFreeDimNone | | neither dim free to be hetero in mat list | +| kMatFreeDim1 | | allow 1st dim of mats in list to be hetero | +| kMatFreeDim2 | | allow 2nd dim of mats in list to be hetero | + + + + + +### data_t + +```cpp +using lds::data_t = double; +``` + + + +Type of all data in library. If need 32b, change `double` to `float`. This could be potentially useful for large scale problems where there are memory constraints. + + +### Vector + +```cpp +using lds::Vector = arma::Col; +``` + + + +### Matrix + +```cpp +using lds::Matrix = arma::Mat; +``` + + + +### Cube + +```cpp +using lds::Cube = arma::Cube; +``` + + + +### View + +```cpp +using lds::View = arma::subview; +``` + + + + +## Function Details + +### Limit + +```cpp +inline void Limit( + std::vector< data_t > & x, + data_t lb, + data_t ub +) +``` + + + +### Limit + +```cpp +inline void Limit( + Vector & x, + data_t lb, + data_t ub +) +``` + + + +### Limit + +```cpp +inline void Limit( + Matrix & x, + data_t lb, + data_t ub +) +``` + + + +### Reassign + +```cpp +inline void Reassign( + Vector & some, + const Vector & other, + const std::string & parenthetical ="Reassign" +) +``` + + + +**Parameters**: + + * **some** some Vector + * **other** other Vector + * **parenthetical** optional description provided by caller to ease debugging + + +### Reassign + +```cpp +inline void Reassign( + Matrix & some, + const Matrix & other, + const std::string & parenthetical ="Reassign" +) +``` + + + +**Parameters**: + + * **some** some Matrix + * **other** other Matrix + * **parenthetical** optional description provided by caller to ease debugging + + +### ForceSymPD + +```cpp +void ForceSymPD( + Matrix & X +) +``` + + + +**Parameters**: + + * **X** mutated matrix + + +### ForceSymMinEig + +```cpp +void ForceSymMinEig( + Matrix & X, + data_t eig_min =0 +) +``` + + + +**Parameters**: + + * **X** mutated matrix + * **eig_min** [optional] minimum eigen value + + +### lq + +```cpp +void lq( + Matrix & L, + Matrix & Qt, + const Matrix & X +) +``` + + + +**Parameters**: + + * **L** lower triangle matrix + * **Qt** orthonormal matrix (transposed cf QR decomp) + * **X** matrix being decomposed + + +### calcCov + +```cpp +Matrix calcCov( + const Matrix & A, + const Matrix & B +) +``` + + + +**Parameters**: + + * **A** some matrix + * **B** some other matrix + + +**Return**: covariance + + +## Attribute Details + +### kInf + +```cpp +static const data_t kInf = std::numeric_limits::infinity(); +``` + + + +### kPi + +```cpp +static const data_t kPi = arma::datum::pi; +``` + + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:29 EDT diff --git a/misc/docs-hugo/content/docs/api/Namespaces/namespacelds_1_1gaussian.md b/misc/docs-hugo/content/docs/api/Namespaces/namespacelds_1_1gaussian.md index 7f4734fa..ecd1b81b 100644 --- a/misc/docs-hugo/content/docs/api/Namespaces/namespacelds_1_1gaussian.md +++ b/misc/docs-hugo/content/docs/api/Namespaces/namespacelds_1_1gaussian.md @@ -1,30 +1,30 @@ ---- -title: lds::gaussian -summary: Linear Dynamical Systems with Gaussian observations. - ---- - -# lds::gaussian - -Linear Dynamical Systems with Gaussian observations.
- -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::gaussian::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1controller/)**
Gaussian-observation [Controller]() Type. | -| class | **[lds::gaussian::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fit/)**
GLDS [Fit]() Type. | -| class | **[lds::gaussian::FitEM](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fitem/)**
GLDS E-M [Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fit/) Type. | -| class | **[lds::gaussian::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1fitssid/)**
Subspace Identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1ssid/)) for GLDS. | -| class | **[lds::gaussian::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1switchedcontroller/)**
Gaussian-observation [SwitchedController]() Type. | -| class | **[lds::gaussian::System](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1system/)**
Gaussian LDS Type. | - - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:04 Eastern Daylight Time +--- +title: lds::gaussian +summary: Linear Dynamical Systems with Gaussian observations. + +--- + +# lds::gaussian + +Linear Dynamical Systems with Gaussian observations.
+ +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::gaussian::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_controller/)**
Gaussian-observation [Controller]() Type. | +| class | **[lds::gaussian::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit/)**
GLDS [Fit]() Type. | +| class | **[lds::gaussian::FitEM](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit_e_m/)**
GLDS E-M [Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit/) Type. | +| class | **[lds::gaussian::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_fit_s_s_i_d/)**
Subspace Identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1_s_s_i_d/)) for GLDS. | +| class | **[lds::gaussian::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_switched_controller/)**
Gaussian-observation [SwitchedController]() Type. | +| class | **[lds::gaussian::System](/lds-ctrl-est/docs/api/classes/classlds_1_1gaussian_1_1_system/)**
Gaussian LDS Type. | + + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:29 EDT diff --git a/misc/docs-hugo/content/docs/api/Namespaces/namespacelds_1_1poisson.md b/misc/docs-hugo/content/docs/api/Namespaces/namespacelds_1_1poisson.md index d3ee26e8..ae52b647 100644 --- a/misc/docs-hugo/content/docs/api/Namespaces/namespacelds_1_1poisson.md +++ b/misc/docs-hugo/content/docs/api/Namespaces/namespacelds_1_1poisson.md @@ -1,56 +1,56 @@ ---- -title: lds::poisson -summary: Linear Dynamical Systems with Poisson observations. - ---- - -# lds::poisson - -Linear Dynamical Systems with Poisson observations.
- -## Classes - -| | Name | -| -------------- | -------------- | -| class | **[lds::poisson::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1controller/)**
PLDS [Controller]() Type. | -| class | **[lds::poisson::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1fit/)**
PLDS [Fit]() Type. | -| class | **[lds::poisson::FitEM](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1fitem/)**
PLDS E-M [Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1fit/) Type. | -| class | **[lds::poisson::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1fitssid/)**
Subspace Identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1ssid/)) for PLDS. | -| class | **[lds::poisson::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1switchedcontroller/)**
Poisson-observation [SwitchedController]() Type. | -| class | **[lds::poisson::System](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1system/)**
Poisson [System]() type. | - -## Attributes - -| | Name | -| -------------- | -------------- | -| std::random_device | **[rd](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/#variable-rd)**
random device for simulating poisson data | -| std::mt19937 | **[rng](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/#variable-rng)**
random number generator for simulating poisson data | - - - -## Attribute Details - -### rd - -```cpp -static std::random_device rd; -``` - - - -### rng - -```cpp -static std::mt19937 rng = std::mt19937( - rd()); -``` - - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:04 Eastern Daylight Time +--- +title: lds::poisson +summary: Linear Dynamical Systems with Poisson observations. + +--- + +# lds::poisson + +Linear Dynamical Systems with Poisson observations.
+ +## Classes + +| | Name | +| -------------- | -------------- | +| class | **[lds::poisson::Controller](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_controller/)**
PLDS [Controller]() Type. | +| class | **[lds::poisson::Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_fit/)**
PLDS [Fit]() Type. | +| class | **[lds::poisson::FitEM](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_fit_e_m/)**
PLDS E-M [Fit](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_fit/) Type. | +| class | **[lds::poisson::FitSSID](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_fit_s_s_i_d/)**
Subspace Identification ([SSID](/lds-ctrl-est/docs/api/classes/classlds_1_1_s_s_i_d/)) for PLDS. | +| class | **[lds::poisson::SwitchedController](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_switched_controller/)**
Poisson-observation [SwitchedController]() Type. | +| class | **[lds::poisson::System](/lds-ctrl-est/docs/api/classes/classlds_1_1poisson_1_1_system/)**
Poisson [System]() type. | + +## Attributes + +| | Name | +| -------------- | -------------- | +| std::random_device | **[rd](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/#variable-rd)**
random device for simulating poisson data | +| std::mt19937 | **[rng](/lds-ctrl-est/docs/api/namespaces/namespacelds_1_1poisson/#variable-rng)**
random number generator for simulating poisson data | + + + +## Attribute Details + +### rd + +```cpp +static std::random_device rd; +``` + + + +### rng + +```cpp +static std::mt19937 rng = std::mt19937( + rd()); +``` + + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:29 EDT diff --git a/misc/docs-hugo/content/docs/api/Namespaces/namespacestd.md b/misc/docs-hugo/content/docs/api/Namespaces/namespacestd.md new file mode 100644 index 00000000..c395bcc9 --- /dev/null +++ b/misc/docs-hugo/content/docs/api/Namespaces/namespacestd.md @@ -0,0 +1,18 @@ +--- +title: std + +--- + +# std + +
+ + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/api/Pages/_index.md b/misc/docs-hugo/content/docs/api/Pages/_index.md index 75a00e31..35ced42c 100644 --- a/misc/docs-hugo/content/docs/api/Pages/_index.md +++ b/misc/docs-hugo/content/docs/api/Pages/_index.md @@ -1,16 +1,16 @@ ---- -title: Pages - ---- - -# Pages - - - - - - - -------------------------------- - -Updated on 19 May 2022 at 17:16:06 Eastern Daylight Time +--- +title: Pages + +--- + +# Pages + + + + + + + +------------------------------- + +Updated on 3 April 2025 at 13:48:30 EDT diff --git a/misc/docs-hugo/content/docs/getting-started/getting-started.md b/misc/docs-hugo/content/docs/getting-started/getting-started.md index c68271df..fe624740 100644 --- a/misc/docs-hugo/content/docs/getting-started/getting-started.md +++ b/misc/docs-hugo/content/docs/getting-started/getting-started.md @@ -26,16 +26,16 @@ Homebrew is "The Missing Package Manager for macOS" which will make installing l /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``` -You can then use it to install CMake and gfortran: +You can then use it to install CMake, gfortran, and pkg-config: ```shell -brew install cmake gfortran +brew install cmake gfortran pkg-config ``` ## Linux Pre-requisites You'll need Git, CMake, GCC, gfortran, etc. ```shell -sudo apt install git cmake pkg-config gfortran curl zip unzip tar build-essential +sudo apt install git cmake pkg-config gfortran curl zip unzip tar build-essential ninja-build ``` ## Windows Installation diff --git a/misc/docs-hugo/content/docs/terminology/control-estimation.md b/misc/docs-hugo/content/docs/terminology/control-estimation.md index 6f951be9..2fde743c 100644 --- a/misc/docs-hugo/content/docs/terminology/control-estimation.md +++ b/misc/docs-hugo/content/docs/terminology/control-estimation.md @@ -63,3 +63,7 @@ Integral action and the {{}} \Delta \mathbf{u} {{}} control law c ## Calculating reference state-control from output In cases where an output reference is supplied and the goal is to track either a static or slowly varying output, users do not have to produce {{}} \mathbf{x}^{\rm ref} {{}} and {{}} \mathbf{u}^{\rm ref} {{}}. Methods are provided for calculating the state and control that would be required to reach the reference output at steady state (`lds::Controller::ControlOutputReference`). This is achieved by linearly-constrained least squares. For single-output systems, it results in an exact solution; however, for multi-output problems it provides a least squares comprimise across outputs. +## Model Predictive Control +Model Predictive Control (MPC) is an advanced control strategy that utilizes a dynamic model of the system to predict and optimize future behavior over a specified time horizon. At each control step, MPC solves an optimization problem to determine the control inputs that minimize a cost function, which typically includes terms for tracking desired reference trajectories and penalizing excessive control efforts. This approach allows MPC to handle multivariable systems with constraints effectively, making it suitable for complex industrial applications. + +In the context of linear systems, the optimization problem within MPC can be formulated as a quadratic program. This involves defining a quadratic cost function over the prediction horizon, which balances the trade-off between tracking performance and control effort. The solution to this quadratic program yields the optimal control inputs that drive the system towards the desired state while respecting operational constraints. Tools like the Operator Splitting Quadratic Program (OSQP) solver are often employed to efficiently solve these optimization problems in real-time. \ No newline at end of file diff --git a/misc/docs-hugo/content/issues-contributing.md b/misc/docs-hugo/content/issues-contributing.md index 1930e065..549e927d 100644 --- a/misc/docs-hugo/content/issues-contributing.md +++ b/misc/docs-hugo/content/issues-contributing.md @@ -3,3 +3,12 @@ If you encounter bugs when using this library or have specific feature requests # Contributing We welcome any community contributions to this project. Please fork the repository and if possible use `clang-format` and `clang-tidy` to conform to the coding format/style of this repository. + +When editing any documentation/guides, please use the markdown docs in `misc/docs-hugo` instead of directly editing the HTML docs. +This may require having `hugo`, `graphviz`, `rsync` and `doxygen` installed through `brew`, as well as `doxybook2` installed through a git clone. + +Clone the `doxybook2` repository online and place the executable in your `usr/local/bin` folder or another `bin` folder. +Run `sudo chmod +x /usr/local/bin/doxybook2` to give doxybook2 permissions. Run `doxybook2 --help` to ensure that this works properly. If permission is still denied, navigate to System Preferences > Security & Privacy > General. +You should see a message at the bottom that says: "doxybook2 was blocked from use because it is not from an identified developer." Click Allow Anyway. + +Updated docs can be built by running `cd scripts` and `./update-docs.sh`. After a successful build, navigate to `/misc/docs-hugo/` and run `hugo server` to create a local host of the website. Access the website using local host to ensure the correct results. \ No newline at end of file diff --git a/misc/docs-hugo/resources/_gen/assets/book.scss_b807c86e8030af4cdc30edccea379f5f.content b/misc/docs-hugo/resources/_gen/assets/book.scss_b807c86e8030af4cdc30edccea379f5f.content new file mode 100644 index 00000000..6dc6c4a7 --- /dev/null +++ b/misc/docs-hugo/resources/_gen/assets/book.scss_b807c86e8030af4cdc30edccea379f5f.content @@ -0,0 +1 @@ +@charset "UTF-8";:root{--gray-100:#f8f9fa;--gray-200:#e9ecef;--gray-500:#adb5bd;--color-link:#0055bb;--color-visited-link:#8440f1;--body-background:white;--body-font-color:black;--icon-filter:none;--hint-color-info:#6bf;--hint-color-warning:#fd6;--hint-color-danger:#f66}@media(prefers-color-scheme:dark){:root{--gray-100:rgba(255, 255, 255, 0.1);--gray-200:rgba(255, 255, 255, 0.2);--gray-500:rgba(255, 255, 255, 0.5);--color-link:#84b2ff;--color-visited-link:#b88dff;--body-background:#343a40;--body-font-color:#e9ecef;--icon-filter:brightness(0) invert(1);--hint-color-info:#6bf;--hint-color-warning:#fd6;--hint-color-danger:#f66}}/*!normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css*/html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}.flex{display:flex}.flex-auto{flex:auto}.flex-even{flex:1 1}.flex-wrap{flex-wrap:wrap}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.align-center{align-items:center}.mx-auto{margin:0 auto}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.hidden{display:none}input.toggle{height:0;width:0;overflow:hidden;opacity:0;position:absolute}.clearfix::after{content:"";display:table;clear:both}html{font-size:16px;scroll-behavior:smooth;touch-action:manipulation}body{min-width:20rem;color:var(--body-font-color);background:var(--body-background);letter-spacing:.33px;font-weight:400;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box}body *{box-sizing:inherit}h1,h2,h3,h4,h5{font-weight:400}a{text-decoration:none;color:var(--color-link)}img{vertical-align:baseline}:focus{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}aside nav ul{padding:0;margin:0;list-style:none}aside nav ul li{margin:1em 0;position:relative}aside nav ul a{display:block}aside nav ul a:hover{opacity:.5}aside nav ul ul{padding-inline-start:1rem}ul.pagination{display:flex;justify-content:center;list-style-type:none}ul.pagination .page-item a{padding:1rem}.container{max-width:80rem;margin:0 auto}.book-icon{filter:var(--icon-filter)}.book-brand{margin-top:0}.book-brand img{height:1.5em;width:auto;vertical-align:middle;margin-inline-end:.5rem}.book-menu{flex:0 0 16rem;font-size:.875rem}.book-menu .book-menu-content{width:16rem;padding:1rem;background:var(--body-background);position:fixed;top:0;bottom:0;overflow-x:hidden;overflow-y:auto}.book-menu a,.book-menu label{color:inherit;cursor:pointer;word-wrap:break-word}.book-menu a.active{color:var(--color-link)}.book-menu input.toggle+label+ul{display:none}.book-menu input.toggle:checked+label+ul{display:block}.book-menu input.toggle+label::after{content:"▸"}.book-menu input.toggle:checked+label::after{content:"▾"}body[dir=rtl] .book-menu input.toggle+label::after{content:"◂"}body[dir=rtl] .book-menu input.toggle:checked+label::after{content:"▾"}.book-section-flat{margin-bottom:2rem}.book-section-flat:not(:first-child){margin-top:2rem}.book-section-flat>a,.book-section-flat>span,.book-section-flat>label{font-weight:bolder}.book-section-flat>ul{padding-inline-start:0}.book-page{min-width:20rem;flex-grow:1;padding:1rem}.book-post{margin-bottom:3rem}.book-header{display:none;margin-bottom:1rem}.book-header label{line-height:0}.book-header img.book-icon{height:1.5em;width:1.5em}.book-search{position:relative;margin:1rem 0;border-bottom:1px solid transparent}.book-search input{width:100%;padding:.5rem;border:0;border-radius:.25rem;background:var(--gray-100);color:var(--body-font-color)}.book-search input:required+.book-search-spinner{display:block}.book-search .book-search-spinner{position:absolute;top:0;margin:.5rem;margin-inline-start:calc(100% - 1.5rem);width:1rem;height:1rem;border:1px solid transparent;border-top-color:var(--body-font-color);border-radius:50%;animation:spin 1s ease infinite}@keyframes spin{100%{transform:rotate(360deg)}}.book-search small{opacity:.5}.book-toc{flex:0 0 16rem;font-size:.75rem}.book-toc .book-toc-content{width:16rem;padding:1rem;position:fixed;top:0;bottom:0;overflow-x:hidden;overflow-y:auto}.book-toc img{height:1em;width:1em}.book-toc nav>ul>li:first-child{margin-top:0}.book-footer{padding-top:1rem;font-size:.875rem}.book-footer img{height:1em;width:1em;margin-inline-end:.5rem}.book-comments{margin-top:1rem}.book-languages{position:relative;overflow:visible;padding:1rem;margin:-1rem}.book-languages ul{margin:0;padding:0;list-style:none}.book-languages ul li{white-space:nowrap;cursor:pointer}.book-languages:hover .book-languages-list,.book-languages:focus .book-languages-list,.book-languages:focus-within .book-languages-list{display:block}.book-languages .book-languages-list{display:none;position:absolute;bottom:100%;left:0;padding:.5rem 0;background:var(--body-background);box-shadow:0 0 .25rem rgba(0,0,0,.1)}.book-languages .book-languages-list li img{opacity:.25}.book-languages .book-languages-list li.active img,.book-languages .book-languages-list li:hover img{opacity:initial}.book-languages .book-languages-list a{color:inherit;padding:.5rem 1rem}.book-home{padding:1rem}.book-menu-content,.book-toc-content,.book-page,.book-header aside,.markdown{transition:.2s ease-in-out;transition-property:transform,margin,opacity,visibility;will-change:transform,margin,opacity}@media screen and (max-width:56rem){#menu-control,#toc-control{display:inline}.book-menu{visibility:hidden;margin-inline-start:-16rem;font-size:16px;z-index:1}.book-toc{display:none}.book-header{display:block}#menu-control:focus~main label[for=menu-control]{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}#menu-control:checked~main .book-menu{visibility:initial}#menu-control:checked~main .book-menu .book-menu-content{transform:translateX(16rem);box-shadow:0 0 .5rem rgba(0,0,0,.1)}#menu-control:checked~main .book-page{opacity:.25}#menu-control:checked~main .book-menu-overlay{display:block;position:absolute;top:0;bottom:0;left:0;right:0}#toc-control:focus~main label[for=toc-control]{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}#toc-control:checked~main .book-header aside{display:block}body[dir=rtl] #menu-control:checked~main .book-menu .book-menu-content{transform:translateX(-16rem)}}@media screen and (min-width:80rem){.book-page,.book-menu .book-menu-content,.book-toc .book-toc-content{padding:2rem 1rem}}@font-face{font-family:roboto;font-style:normal;font-weight:400;font-display:swap;src:local(""),url(fonts/roboto-v27-latin-regular.woff2)format("woff2"),url(fonts/roboto-v27-latin-regular.woff)format("woff")}@font-face{font-family:roboto;font-style:normal;font-weight:700;font-display:swap;src:local(""),url(fonts/roboto-v27-latin-700.woff2)format("woff2"),url(fonts/roboto-v27-latin-700.woff)format("woff")}@font-face{font-family:roboto mono;font-style:normal;font-weight:400;font-display:swap;src:local(""),url(fonts/roboto-mono-v13-latin-regular.woff2)format("woff2"),url(fonts/roboto-mono-v13-latin-regular.woff)format("woff")}body{font-family:roboto,sans-serif}code{font-family:roboto mono,monospace}@media print{.book-menu,.book-footer,.book-toc{display:none}.book-header,.book-header aside{display:block}main{display:block!important}}.markdown{line-height:1.6}.markdown>:first-child{margin-top:0}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{font-weight:400;line-height:1;margin-top:1.5em;margin-bottom:1rem}.markdown h1 a.anchor,.markdown h2 a.anchor,.markdown h3 a.anchor,.markdown h4 a.anchor,.markdown h5 a.anchor,.markdown h6 a.anchor{opacity:0;font-size:.75em;vertical-align:middle;text-decoration:none}.markdown h1:hover a.anchor,.markdown h1 a.anchor:focus,.markdown h2:hover a.anchor,.markdown h2 a.anchor:focus,.markdown h3:hover a.anchor,.markdown h3 a.anchor:focus,.markdown h4:hover a.anchor,.markdown h4 a.anchor:focus,.markdown h5:hover a.anchor,.markdown h5 a.anchor:focus,.markdown h6:hover a.anchor,.markdown h6 a.anchor:focus{opacity:initial}.markdown h4,.markdown h5,.markdown h6{font-weight:bolder}.markdown h5{font-size:.875em}.markdown h6{font-size:.75em}.markdown b,.markdown optgroup,.markdown strong{font-weight:bolder}.markdown a{text-decoration:none}.markdown a:hover{text-decoration:underline}.markdown a:visited{color:var(--color-visited-link)}.markdown img{max-width:100%}.markdown code{padding:0 .25rem;background:var(--gray-200);border-radius:.25rem;font-size:.875em}.markdown pre{padding:1rem;background:var(--gray-100);border-radius:.25rem;overflow-x:auto}.markdown pre code{padding:0;background:0 0}.markdown blockquote{margin:1rem 0;padding:.5rem 1rem .5rem .75rem;border-inline-start:.25rem solid var(--gray-200);border-radius:.25rem}.markdown blockquote :first-child{margin-top:0}.markdown blockquote :last-child{margin-bottom:0}.markdown table{overflow:auto;display:block;border-spacing:0;border-collapse:collapse;margin-top:1rem;margin-bottom:1rem}.markdown table tr th,.markdown table tr td{padding:.5rem 1rem;border:1px solid var(--gray-200)}.markdown table tr:nth-child(2n){background:var(--gray-100)}.markdown hr{height:1px;border:none;background:var(--gray-200)}.markdown ul,.markdown ol{padding-inline-start:2rem}.markdown dl dt{font-weight:bolder;margin-top:1rem}.markdown dl dd{margin-inline-start:0;margin-bottom:1rem}.markdown .highlight table tr td:nth-child(1) pre{margin:0;padding-inline-end:0}.markdown .highlight table tr td:nth-child(2) pre{margin:0;padding-inline-start:0}.markdown details{padding:1rem;border:1px solid var(--gray-200);border-radius:.25rem}.markdown details summary{line-height:1;padding:1rem;margin:-1rem;cursor:pointer}.markdown details[open] summary{margin-bottom:0}.markdown figure{margin:1rem 0}.markdown figure figcaption p{margin-top:0}.markdown-inner>:first-child{margin-top:0}.markdown-inner>:last-child{margin-bottom:0}.markdown .book-expand{margin-top:1rem;margin-bottom:1rem;border:1px solid var(--gray-200);border-radius:.25rem;overflow:hidden}.markdown .book-expand .book-expand-head{background:var(--gray-100);padding:.5rem 1rem;cursor:pointer}.markdown .book-expand .book-expand-content{display:none;padding:1rem}.markdown .book-expand input[type=checkbox]:checked+.book-expand-content{display:block}.markdown .book-tabs{margin-top:1rem;margin-bottom:1rem;border:1px solid var(--gray-200);border-radius:.25rem;overflow:hidden;display:flex;flex-wrap:wrap}.markdown .book-tabs label{display:inline-block;padding:.5rem 1rem;border-bottom:1px transparent;cursor:pointer}.markdown .book-tabs .book-tabs-content{order:999;width:100%;border-top:1px solid var(--gray-100);padding:1rem;display:none}.markdown .book-tabs input[type=radio]:checked+label{border-bottom:1px solid var(--color-link)}.markdown .book-tabs input[type=radio]:checked+label+.book-tabs-content{display:block}.markdown .book-tabs input[type=radio]:focus+label{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}.markdown .book-columns{margin-left:-1rem;margin-right:-1rem}.markdown .book-columns>div{margin:1rem 0;min-width:10rem;padding:0 1rem}.markdown a.book-btn{display:inline-block;font-size:.875rem;color:var(--color-link);line-height:2rem;padding:0 1rem;border:1px solid var(--color-link);border-radius:.25rem;cursor:pointer}.markdown a.book-btn:hover{text-decoration:none}.markdown .book-hint.info{border-color:#6bf;background-color:rgba(102,187,255,.1)}.markdown .book-hint.warning{border-color:#fd6;background-color:rgba(255,221,102,.1)}.markdown .book-hint.danger{border-color:#f66;background-color:rgba(255,102,102,.1)} \ No newline at end of file diff --git a/misc/docs-hugo/resources/_gen/assets/book.scss_b807c86e8030af4cdc30edccea379f5f.json b/misc/docs-hugo/resources/_gen/assets/book.scss_b807c86e8030af4cdc30edccea379f5f.json new file mode 100644 index 00000000..1790550f --- /dev/null +++ b/misc/docs-hugo/resources/_gen/assets/book.scss_b807c86e8030af4cdc30edccea379f5f.json @@ -0,0 +1 @@ +{"Target":"book.min.57f7f660871517a5bfcfb5e2de853d806f7e34d94ebd5f3f3bad62e9ddbae209.css","MediaType":"text/css","Data":{"Integrity":"sha256-V/f2YIcVF6W/z7Xi3oU9gG9+NNlOvV8/O61i6d264gk="}} \ No newline at end of file diff --git a/scripts/update-docs.sh b/scripts/update-docs.sh index 5c65947a..2c78b380 100755 --- a/scripts/update-docs.sh +++ b/scripts/update-docs.sh @@ -6,6 +6,8 @@ # generate site cd ../misc/docs-hugo && hugo && cd ../../scripts -# remove existing docs/ and add new in its place -rm -rf ../docs/* && cp -r ../misc/docs-hugo/public/* ../docs/ +# create docs directory if it doesn't exist +mkdir -p ../docs +# update docs by copying new files and overwriting changed ones +cp -R ../misc/docs-hugo/public/* ../docs/ \ No newline at end of file