16#include <boost/math/distributions/students_t.hpp>
47 return "Experimental/DataProcessor";
54 ImGui::InputInt(
"p", &
_p);
55 ImGui::InputInt(
"q", &
_q);
56 static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
57 if (ImGui::BeginTable(
"##table1", 3, flags))
59 ImGui::TableSetupColumn(
"ARMA Parameter");
60 ImGui::TableSetupColumn(
"estimate");
61 ImGui::TableSetupColumn(
"p");
62 ImGui::TableHeadersRow();
64 for (
int table_row = 0; table_row <
_x.size(); table_row++)
66 ImGui::TableNextRow();
67 ImGui::TableNextColumn();
70 ImGui::Text(
"phi %d", table_row + 1);
74 ImGui::Text(
"theta %d", table_row -
_p + 1);
76 ImGui::TableNextColumn();
77 ImGui::Text(
"%f",
_x(table_row));
78 ImGui::TableNextColumn();
79 ImGui::Text(
"%f",
_emp_sig(table_row));
102 if (j.contains(
"deque_size"))
108 j.at(
"p").get_to(
_p);
112 j.at(
"q").get_to(
_q);
127 _x = Eigen::VectorXd::Zero(
_p +
_q);
131 _m =
static_cast<int>(std::max(
_p,
_q));
145 int acf_size =
static_cast<int>(y.size());
149 int p_approx = p + 3;
153 double mean = y.mean();
155 for (
int i = 0; i < acf_size; i++)
157 var += (y(i) - mean) * (y(i) - mean);
160 for (
int tau = 0; tau < p_approx + 1; tau++)
163 for (
int i = 0; i < acf_size - tau; i++)
165 cov += (y(i) - mean) * (y(i + tau) - mean);
167 acf(tau) = cov / var;
174 int pacf_size =
static_cast<int>(y.size());
177 int p_approx = p + 3;
179 Eigen::VectorXd phi_tau = Eigen::VectorXd::Zero(p_approx);
180 Eigen::VectorXd phi_tau_i = Eigen::VectorXd::Zero(p_approx);
181 Eigen::VectorXd phi_initial = Eigen::VectorXd::Zero(p_approx);
190#if defined(__GNUC__) || defined(__clang__)
191 #pragma GCC diagnostic push
192 #pragma GCC diagnostic ignored "-Wnull-dereference"
194 phi_tau_i(0) = pacf(0);
195#if defined(__GNUC__) || defined(__clang__)
196 #pragma GCC diagnostic pop
198 sum1 = acf(1) * acf(1);
199 sum2 = acf(1) * acf(1);
201 e_hat_initial(0) = 0;
203 for (
int tau = 2; tau <= pacf_size; tau++)
206 if (tau == p_approx + 1)
208 phi_initial = phi_tau_i;
212 if (tau < p_approx + 1)
214 pacf(tau - 1) = (acf(tau) - sum1) / (1 - sum2);
218 for (
int i = 0; i < tau - 1; i++)
220 phi_tau(i) = (phi_tau_i(i) - pacf(tau - 1) * phi_tau_i(tau - i - 2));
221 sum1 += phi_tau(i) * acf(tau - i);
222 sum2 += phi_tau(i) * acf(i + 1);
225 phi_tau_i(tau - 1) = pacf(tau - 1);
226 sum1 += pacf(tau - 1) * acf(1);
227 sum2 += pacf(tau - 1) * acf(tau);
234 for (
int iter = 0; iter < p_approx; iter++)
236 sum3 += y(tau - iter - 2) * phi_initial(iter);
238 e_hat_initial(tau - 1) = y(tau - 1) - sum3;
243 e_hat_initial(tau - 1) = 0;
250 for (
int t = m; t < y.size(); t++)
252 for (
int i = 0; i < p; i++)
254 A(t - m, i) = y(t - i - 1);
256 for (
int i = p; i < p + q; i++)
258 A(t - m, i) = -e_hat(t - i + p - 1);
267 Eigen::VectorXd acf = Eigen::VectorXd::Zero(deque_size);
269 Eigen::VectorXd pacf = Eigen::VectorXd::Zero(deque_size - 1);
270 Eigen::VectorXd e_hat = Eigen::VectorXd::Zero(deque_size);
272 Eigen::MatrixXd A = Eigen::MatrixXd::Zero(deque_size - m, p + q);
274 Eigen::VectorXd t = Eigen::VectorXd::Zero(p + q);
275 Eigen::MatrixXd ata_inv = Eigen::MatrixXd::Zero(p + q, p + q);
278 int df = deque_size - p - q - 1;
279 boost::math::students_t dist(df);
287 for (
int it = 0; it < 2; it++)
291 x = (A.transpose() * A).ldlt().solve(A.transpose() * y.tail(deque_size - m));
293 for (
int i_HR = 0; i_HR < m; i_HR++)
295 y_hat(i_HR) = y(i_HR);
297 y_hat.tail(deque_size - m) = A * x;
302 double e_square = e_hat.transpose() * e_hat;
303 double var_e = e_square / df;
304 ata_inv = (A.transpose() * A).inverse();
305 for (
int j = 0; j < p + q; j++)
307 t(j) = x(j) / sqrt(var_e * ata_inv(j, j));
308 emp_sig(j) = 2 * boost::math::pdf(dist, t(j));
314 auto obs = std::static_pointer_cast<const ImuObs>(queue.
extract_front());
315 auto newImuObs = std::make_shared<ImuObs>(obs->imuPos);
323 const Eigen::Vector3d acc = obs->p_acceleration;
324 const Eigen::Vector3d gyro = obs->p_angularRate;
325 _y.row(
_k) << acc.transpose(), gyro.transpose();
328 for (
int obs_nr = 0; obs_nr <
_num_obs; obs_nr++)
347 _m =
static_cast<int>(std::max(
_p,
_q));
355 for (arma_it = 0; arma_it <
_p +
_q; arma_it++)
380 newImuObs->insTime = obs->insTime;
381 newImuObs->p_acceleration = Eigen::Vector3d(
_y_hat_t.head(3));
382 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.
OutputPin * CreateOutputPin(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.
std::string nameId() const
Node name and id.
std::string name
Name of the Node.
InputPin * CreateInputPin(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.
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