18#include <boost/math/distributions/students_t.hpp>
49 return "Experimental/DataProcessor";
56 ImGui::InputInt(
"p", &
_p);
57 ImGui::InputInt(
"q", &
_q);
58 static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
59 if (ImGui::BeginTable(
"##table1", 3, flags))
61 ImGui::TableSetupColumn(
"ARMA Parameter");
62 ImGui::TableSetupColumn(
"estimate");
63 ImGui::TableSetupColumn(
"p");
64 ImGui::TableHeadersRow();
66 for (
int table_row = 0; table_row <
_x.size(); table_row++)
68 ImGui::TableNextRow();
69 ImGui::TableNextColumn();
72 ImGui::Text(
"phi %d", table_row + 1);
76 ImGui::Text(
"theta %d", table_row -
_p + 1);
78 ImGui::TableNextColumn();
79 ImGui::Text(
"%f",
_x(table_row));
80 ImGui::TableNextColumn();
81 ImGui::Text(
"%f",
_emp_sig(table_row));
104 if (j.contains(
"deque_size"))
110 j.at(
"p").get_to(
_p);
114 j.at(
"q").get_to(
_q);
129 _x = Eigen::VectorXd::Zero(
_p +
_q);
133 _m =
static_cast<int>(std::max(
_p,
_q));
147 int acf_size =
static_cast<int>(y.size());
151 int p_approx = p + 3;
155 double mean = y.mean();
157 for (
int i = 0; i < acf_size; i++)
159 var += (y(i) - mean) * (y(i) - mean);
162 for (
int tau = 0; tau < p_approx + 1; tau++)
165 for (
int i = 0; i < acf_size - tau; i++)
167 cov += (y(i) - mean) * (y(i + tau) - mean);
169 acf(tau) = cov / var;
176 int pacf_size =
static_cast<int>(y.size());
179 int p_approx = p + 3;
181 Eigen::VectorXd phi_tau = Eigen::VectorXd::Zero(p_approx);
182 Eigen::VectorXd phi_tau_i = Eigen::VectorXd::Zero(p_approx);
183 Eigen::VectorXd phi_initial = Eigen::VectorXd::Zero(p_approx);
192#if defined(__GNUC__) || defined(__clang__)
193 #pragma GCC diagnostic push
194 #pragma GCC diagnostic ignored "-Wnull-dereference"
196 phi_tau_i(0) = pacf(0);
197#if defined(__GNUC__) || defined(__clang__)
198 #pragma GCC diagnostic pop
200 sum1 = acf(1) * acf(1);
201 sum2 = acf(1) * acf(1);
203 e_hat_initial(0) = 0;
205 for (
int tau = 2; tau <= pacf_size; tau++)
208 if (tau == p_approx + 1)
210 phi_initial = phi_tau_i;
214 if (tau < p_approx + 1)
216 pacf(tau - 1) = (acf(tau) - sum1) / (1 - sum2);
220 for (
int i = 0; i < tau - 1; i++)
222 phi_tau(i) = (phi_tau_i(i) - pacf(tau - 1) * phi_tau_i(tau - i - 2));
223 sum1 += phi_tau(i) * acf(tau - i);
224 sum2 += phi_tau(i) * acf(i + 1);
227 phi_tau_i(tau - 1) = pacf(tau - 1);
228 sum1 += pacf(tau - 1) * acf(1);
229 sum2 += pacf(tau - 1) * acf(tau);
236 for (
int iter = 0; iter < p_approx; iter++)
238 sum3 += y(tau - iter - 2) * phi_initial(iter);
240 e_hat_initial(tau - 1) = y(tau - 1) - sum3;
245 e_hat_initial(tau - 1) = 0;
252 for (
int t = m; t < y.size(); t++)
254 for (
int i = 0; i < p; i++)
256 A(t - m, i) = y(t - i - 1);
258 for (
int i = p; i < p + q; i++)
260 A(t - m, i) = -e_hat(t - i + p - 1);
269 Eigen::VectorXd acf = Eigen::VectorXd::Zero(deque_size);
271 Eigen::VectorXd pacf = Eigen::VectorXd::Zero(deque_size - 1);
272 Eigen::VectorXd e_hat = Eigen::VectorXd::Zero(deque_size);
274 Eigen::MatrixXd A = Eigen::MatrixXd::Zero(deque_size - m, p + q);
276 Eigen::VectorXd t = Eigen::VectorXd::Zero(p + q);
277 Eigen::MatrixXd ata_inv = Eigen::MatrixXd::Zero(p + q, p + q);
280 int df = deque_size - p - q - 1;
281 boost::math::students_t dist(df);
289 for (
int it = 0; it < 2; it++)
293 x = (A.transpose() * A).ldlt().solve(A.transpose() * y.tail(deque_size - m));
295 for (
int i_HR = 0; i_HR < m; i_HR++)
297 y_hat(i_HR) = y(i_HR);
299 y_hat.tail(deque_size - m) = A * x;
304 double e_square = e_hat.transpose() * e_hat;
305 double var_e = e_square / df;
306 ata_inv = (A.transpose() * A).inverse();
307 for (
int j = 0; j < p + q; j++)
309 t(j) = x(j) / sqrt(var_e * ata_inv(j, j));
310 emp_sig(j) = 2 * boost::math::pdf(dist, t(j));
316 auto obs = std::static_pointer_cast<const ImuObs>(queue.
extract_front());
317 auto newImuObs = std::make_shared<ImuObs>(obs->imuPos);
325 const Eigen::Vector3d acc = obs->p_acceleration;
326 const Eigen::Vector3d gyro = obs->p_angularRate;
327 _y.row(
_k) << acc.transpose(), gyro.transpose();
330 for (
int obs_nr = 0; obs_nr <
_num_obs; obs_nr++)
349 _m =
static_cast<int>(std::max(
_p,
_q));
357 for (arma_it = 0; arma_it <
_p +
_q; arma_it++)
382 newImuObs->insTime = obs->insTime;
383 newImuObs->p_acceleration = Eigen::Vector3d(
_y_hat_t.head(3));
384 newImuObs->p_angularRate = Eigen::Vector3d(
_y_hat_t.tail(3));
nlohmann::json json
json namespace
Utility class for logging to console and file.
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
static std::string type()
Returns the type of the data class.
Node(std::string name)
Constructor.
std::string nameId() const
Node name and id.
std::string name
Name of the Node.
void invokeCallbacks(size_t portIndex, const std::shared_ptr< const NodeData > &data)
Calls all registered callbacks on the specified output port.
bool _hasConfig
Flag if the config window should be shown.
auto extract_front()
Returns a copy of the first element in the container and removes it from the container.
~ARMA() override
Destructor.
Eigen::MatrixXd _y
measurement data
void deinitialize() override
Deinitialize the node.
static std::string category()
String representation of the Class Category.
std::deque< std::shared_ptr< const ImuObs > > _buffer
Buffer used to store Imu observations.
int _m
value of superior order (p or q)
static void pacf_function(Eigen::VectorXd &y, Eigen::VectorXd &acf, int p, Eigen::VectorXd &pacf, Eigen::VectorXd &e_hat_initial)
calculate partial autocorrelation function (PACF) via Durbin-Levinson
static void hannan_rissanen(Eigen::VectorXd &y, int p, int q, int m, int deque_size, Eigen::VectorXd &x, Eigen::VectorXd &emp_sig, Eigen::VectorXd &y_hat)
Calculate ARMA parameters through Hannan-Rissanen.
Eigen::VectorXd _y_hat
ARMA estimates for y_rbm.
int _deque_size
modelling size
void guiConfig() override
ImGui config window which is shown on double click.
Eigen::VectorXd _x
ARMA slope parameters.
static constexpr size_t OUTPUT_PORT_INDEX_IMU_OBS
Flow (ImuObs)
bool initialize() override
Initialize the node.
Eigen::VectorXd _y_hat_t
output container
int _q_mem
q memory to reset for each observation
static void acf_function(Eigen::VectorXd &y, int p, Eigen::VectorXd &acf)
calculate autocorrelation function (ACF)
static std::string typeStatic()
String representation of the Class Type.
Eigen::VectorXd _y_rbm
y (reduced by mean)
std::string type() const override
String representation of the Class Type.
static void matrix_function(Eigen::VectorXd &y, Eigen::VectorXd &e_hat, int p, int q, int m, Eigen::MatrixXd &A)
fill A matrix for least squares
int _num_obs
number of observations (3-axis accelerometer / 3-axis gyro)
void receiveImuObs(InputPin::NodeDataQueue &queue, size_t pinIdx)
Receive Sensor Data.
bool INITIALIZE
parameter initialization indicator
Eigen::VectorXd _emp_sig
empirical significance (p-Value) of parameters
void restore(const json &j) override
Restores the node from a json object.
ARMA()
Default constructor.
json save() const override
Saves the node into a json object.
int _p_mem
p memory to reset for each observation
OutputPin * CreateOutputPin(Node *node, const char *name, Pin::Type pinType, const std::vector< std::string > &dataIdentifier, OutputPin::PinData data=static_cast< void * >(nullptr), int idx=-1)
Create an Output Pin object.
InputPin * CreateInputPin(Node *node, const char *name, Pin::Type pinType, const std::vector< std::string > &dataIdentifier={}, InputPin::Callback callback=static_cast< InputPin::FlowFirableCallbackFunc >(nullptr), InputPin::FlowFirableCheckFunc firable=nullptr, int priority=0, int idx=-1)
Create an Input Pin object.