Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Kalman filter example 12: displaying the equations

 

Kalman filter example 12: displaying the equations is an example to use a Kalman filter that displays the equations.

 

 

 

 

 

 

Technical facts

 

Application type(s)

Operating system(s) or programming environment(s)

IDE(s):

Project type:

C++ standard:

Compiler(s):

Libraries used:

 

 

 

 

 

Qt project file: CppKalmanFilterExample12Desktop.pro

 

QT       += core gui
TEMPLATE = app

QMAKE_CXXFLAGS += -Wall -Wextra -Werror

INCLUDEPATH += \
    ../../Classes/KalmanFilter \
    ../../Classes/CppMatrix \
    ../../Classes/CppQtMatrix \
    ../../Classes/CppTrace

win32 {
  QMAKE_CXXFLAGS += -std=c++11

  #Prevents error:
  #/my_boost_folder/boost/type_traits/detail/has_binary_operator.hp:50: Parse error at "BOOST_JOIN"
  DEFINES += BOOST_TT_HAS_OPERATOR_HPP_INCLUDED

  INCLUDEPATH += E:/boost_1_50_0
  INCLUDEPATH += C:/qwt-6.0.1/include
  INCLUDEPATH += ../../Libraries/fparser4.4.3

  LIBS += \
    -LE:/boost_1_50_0/stage/lib  \
    -lboost_system-mgw44-mt-1_50 \
    -lboost_filesystem-mgw44-mt-1_50 \
    -lboost_regex-mgw44-mt-1_50 \
    -LC:/qwt-6.0.1/lib \
    -lqwtd  #Note: gives error 'QWidget: Must construct a QApplication before a QPaintDevice' when using '-lqwt'

  SOURCES += ../../Libraries/fparser4.4.3/fparser.cc
  HEADERS += ../../Libraries/fparser4.4.3/fparser.hh
}

unix {

  QMAKE_CXXFLAGS += -std=c++11
  LIBS += -lqwt-qt4
  INCLUDEPATH += /usr/include/qwt-qt4
  INCLUDEPATH += ../../Libraries/fparser4.5.1
  SOURCES += ../../Libraries/fparser4.5.1/fparser.cc
  HEADERS += ../../Libraries/fparser4.5.1/fparser.hh
}

SOURCES += \
    ../../Classes/KalmanFilter/kalmanfilter.cpp \
    ../../Classes/KalmanFilter/whitenoisesystem.cpp \
    ../../Classes/CppMatrix/matrix.cpp \
    maindialog.cpp \
    qtmain.cpp \
    qtmaindialog.cpp \
    qtkalmanfilteralgorithmdialog.cpp \
    ../../Classes/CppQtMatrix/qtmatrix.cpp

HEADERS += \
    ../../Classes/KalmanFilter/kalmanfilter.h \
    ../../Classes/KalmanFilter/whitenoisesystem.h \
    ../../Classes/CppMatrix/matrix.h \
    ../../Classes/CppTrace/trace.h \
    maindialog.h \
    qtmaindialog.h \
    qtkalmanfilteralgorithmdialog.h \
    ../../Classes/CppQtMatrix/qtmatrix.h

FORMS += \
    qtmaindialog.ui \
    qtkalmanfilteralgorithmdialog.ui

OTHER_FILES += \
    ../../Classes/CppQtMatrix/Licence.txt

 

 

 

 

 

main.cpp

 

#ifdef _WIN32
#undef __STRICT_ANSI__
#endif

///Kalman filter example
///Adapted from merge from www.adrianboeing.com and http://greg.czerniak.info/guides/kalman1
///following
/// * Simon, Dan. Kalman Filtering. Embedded Systems Programming. June 2001.

#include <iostream>

#include <boost/lexical_cast.hpp>

#include "maindialog.h"
#include "matrix.h"

///Context:
///A car that has a constant acceleration that has its position determined by GPS
///The car its speedometer is not used (as observation(1,1) is equal to 0.0),
///  and gives junk values (as x_real_noise(1) is equal to 10000000.0)
int main()
{
  const double t = 0.1;

  //The name of the states:
  //x: position
  //v: velocity
  const std::vector<std::string> state_names = { "x", "v" };
  const int n_states = static_cast<int>(state_names.size());

  //The real state vector
  //[ position ]
  //[ velocity ]
  const boost::numeric::ublas::vector<double> init_x_real = Matrix::CreateVector( { 0.0, 0.0 } );

  //Real measurement noise
  //[ standard deviation of noise in position ]   [ standard deviation of noise in GPS                       ]
  //[ standard deviation of noise in velocity ] = [ standard deviation of noise in defect/unused speedometer ]
  const boost::numeric::ublas::vector<double> x_real_measurement_noise = Matrix::CreateVector( { 10.0, 10000000.0 } );

  //Guess of the state matrix
  //Position and velocity guess is way off on purpose
  //[ position ]
  //[ velocity ]
  const boost::numeric::ublas::vector<double> x_first_guess = Matrix::CreateVector( { 100.0, 10.0 } );

  //Guess of the covariances
  //[ 1.0   0.0 ]
  //[ 0.0   1.0 ]
  const boost::numeric::ublas::matrix<double> p_first_guess = Matrix::CreateMatrix(2,2, { 1.0, 0.0, 0.0, 1.0 } );

  //Effect of inputs on state
  //Input = gas pedal, which gives acceleration 'a'
  //[ 1.0   0.5 * t * t ]   [teleportation (not used)                 x = 0.5 * a * t * t ]
  //[ 0.0   t           ] = [no effect of teleportation on velocity   v = a * t           ]
  const boost::numeric::ublas::matrix<double> control = Matrix::CreateMatrix(2,2, { 1.0, 0.0, 0.5 * t * t, t } );

  //Estimated measurement noise
  //[ 10.0          0.0 ]   [ Estimated noise in GPS   ?                                                     ]
  //[  0.0   10000000.0 ] = [ ?                        Estimated noise in speedometer (absent in this setup) ]
  const boost::numeric::ublas::matrix<double> measurement_noise = Matrix::CreateMatrix(2,2, { 10.0, 0.0, 0.0, 10000000.0 } );

  //Observational matrix
  //[ 1.0   0.0 ]   [GPS measurement   ?                                         ]
  //[ 0.0   0.0 ] = [?                 Speedometer (absent/unused in this setup) ]
  const boost::numeric::ublas::matrix<double> observation = Matrix::CreateMatrix(2,2, { 1.0, 0.0, 0.0, 0.0 } );

  //Real process noise
  //[ 0.001 ]   [ noise in position ]
  //[ 0.001 ] = [ noise in velocity ]
  const boost::numeric::ublas::vector<double> real_process_noise = Matrix::CreateVector( {0.01,0.01} );

  //Estimated process noise covariance
  //[ 0.01   0.01 ]
  //[ 0.01   0.01 ]
  const boost::numeric::ublas::matrix<double> process_noise = Matrix::CreateMatrix(2,2,{0.01,0.01,0.01,0.01});

  //State transition matrix, the effect of the current state on the next
  //[ 1.0     t ]   [ position keeps its value             a velocity changes the position ]
  //[ 0.0   1.0 ] = [ position has no effect on velocity   a velocity keeps its value      ]
  const boost::numeric::ublas::matrix<double> state_transition = Matrix::CreateMatrix(2,2,{1.0,0.0,t,1.0});

  //There is a constant push on the gas pedal. This has no direct effect on the position,
  //but it does increase velocity with accelation every state transition
  const double acceleration = 1.0;
  const std::vector<std::string> input
    = {
      "0.0",
      boost::lexical_cast<std::string>(acceleration)
    };

  const int time = 250;
  const int lag = 2;
  const MainDialog d(
    time,
    lag,
    control,
    input,
    measurement_noise,
    observation,
    p_first_guess,
    process_noise,
    state_transition,
    init_x_real,
    real_process_noise,
    state_names,
    x_first_guess,
    x_real_measurement_noise);

  //Display header
  {
    const boost::numeric::ublas::vector<std::string> header = d.GetHeader(state_names);
    const std::size_t sz = header.size();
    for (std::size_t i=0; i!=sz; ++i)
    {
      std::cout << header(i);
      if (i != sz - 1) std::cout << ",";
    }
    std::cout << '\n';
  }
  //Display data
  {
    const boost::numeric::ublas::matrix<double>& data = d.GetData();
    const std::size_t n_cols = MainDialog::m_n_curves_per_plot * n_states;
    assert(n_cols == d.GetHeader(state_names).size());
    for (int row=0; row!=time; ++row)
    {
      for (std::size_t col=0; col!=n_cols; ++col)
      {
        std::cout << data(row,col);
        if (col != n_cols - 1) std::cout << ",";
      }
      std::cout << '\n';
    }
  }
}

 

 

 

 

 

maindialog.h

 

#ifndef MAINDIALOG_H
#define MAINDIALOG_H

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>

struct MainDialog
{
  MainDialog(
    const int time,
    const boost::numeric::ublas::matrix<double>& control,
    const std::vector<std::string>& input,
    const boost::numeric::ublas::matrix<double>& measurement_noise,
    const boost::numeric::ublas::matrix<double>& observation,
    const boost::numeric::ublas::matrix<double>& init_covariance_estimate,
    const boost::numeric::ublas::matrix<double>& process_noise_estimate,
    const boost::numeric::ublas::matrix<double>& state_transition,
    const boost::numeric::ublas::vector<double>& init_state_real,
    const boost::numeric::ublas::vector<double>& process_noise_real,
    const std::vector<std::string>& state_names,
    const boost::numeric::ublas::vector<double>& x_first_guess,
    const boost::numeric::ublas::vector<double>& x_real_measurement_noise);

  ///Obtain the simulation data
  const boost::numeric::ublas::matrix<double>& GetData() const { return m_data; }

  ///Obtain the header text from the states
  static const boost::numeric::ublas::vector<std::string> GetHeader(const std::vector<std::string>& state_names);

  ///Get the innovations ('y_squiggle')
  const std::vector<boost::numeric::ublas::vector<double> >& GetInnovations() const
    { return m_innovations; }

  ///Get the innovation covariances ('S')
  const std::vector<boost::numeric::ublas::matrix<double> >& GetInnovationCovariances() const
    { return m_innovation_covariances; }

  ///Get the inputs of each timestep
  const std::vector<boost::numeric::ublas::vector<double> >& GetInputs() const
    { return m_inputs; }

  ///Get the Kalman gains ('K')
  const std::vector<boost::numeric::ublas::matrix<double> >& GetKalmanGains() const
    { return m_kalman_gains; }

  ///Get the measurements ('z_n')
  const std::vector<boost::numeric::ublas::vector<double> >& GetMeasurements() const
    { return m_measurements; }

  ///Get he predicted states (at the beginning of each timestep)
  const std::vector<boost::numeric::ublas::vector<double> >& GetPredictedStates() const
    { return  m_predicted_states; }

  ///The predicted error estimation covariances (at the beginning of each timestep)
  const std::vector<boost::numeric::ublas::matrix<double> >& GetPredictedCovariances() const
    { return m_predicted_covariances; }

  ///Obtain the previous_covariance_estimates ('P_prev')
  const std::vector<boost::numeric::ublas::matrix<double> >& GetPreviousCovarianceEstimates() const
    { return m_previous_covariance_estimates; }

  ///Obtain the previous_state_estimates ('x_prev')
  const std::vector<boost::numeric::ublas::vector<double> >& GetPreviousStateEstimates() const
    { return m_previous_state_estimates; }

  ///The updated error estimation covariances (in the end of each timestep)
  const std::vector<boost::numeric::ublas::matrix<double> >& GetUpdatedCovariances() const
    { return m_updated_covariances; }

  ///The updated state (in the end of each timestep)
  const std::vector<boost::numeric::ublas::vector<double> >& GetUpdatedStates() const
    { return m_updated_states; }

  ///The number of curves per plot. Or: the number of values measured per state per timestep
  ///These are now:
  ///1) real value of [state] at time t
  ///2) measurered value of [state] at time t
  ///3) Kalman estimated value of [state] at time t
  ///4) input of [state] at time t
  static const int m_n_curves_per_plot = 4;

  private:

  //Effect of inputs on state
  const boost::numeric::ublas::matrix<double> m_control;

  ///The simulation data, created by simulation
  boost::numeric::ublas::matrix<double> m_data;

  //Guess of the covariances
  const boost::numeric::ublas::matrix<double> m_init_covariance_estimate;

  //Guess of the state matrix
  const boost::numeric::ublas::vector<double> m_init_state_estimate;

  //Real initial state
  const boost::numeric::ublas::vector<double> m_init_state_real;

  ///The inputs of each timestep
  const std::vector<boost::numeric::ublas::vector<double> > m_inputs;

  ///The innovations ('y_squiggle')
  std::vector<boost::numeric::ublas::vector<double> > m_innovations;

  ///The innovation covariances ('S')
  std::vector<boost::numeric::ublas::matrix<double> > m_innovation_covariances;

  ///The Kalman gains ('K')
  std::vector<boost::numeric::ublas::matrix<double> > m_kalman_gains;

  //Estimated measurement noise
  const boost::numeric::ublas::matrix<double> m_measurement_noise_estimate;

  //Real measurement noise
  const boost::numeric::ublas::vector<double> m_measurement_noise_real;

  ///The measurements ('z_n')
  std::vector<boost::numeric::ublas::vector<double> > m_measurements;

  //Observational matrix
  const boost::numeric::ublas::matrix<double> m_observation;

  ///The predicted state (at the beginning of each timestep)
  std::vector<boost::numeric::ublas::vector<double> > m_predicted_states;

  ///The predicted error estimation covariances (at the beginning of each timestep)
  std::vector<boost::numeric::ublas::matrix<double> > m_predicted_covariances;

  ///Obtain the previous_covariance_estimates ('P_prev')
  std::vector<boost::numeric::ublas::matrix<double> > m_previous_covariance_estimates;

  ///Obtain the previous_state_estimates ('x_prev')
  std::vector<boost::numeric::ublas::vector<double> > m_previous_state_estimates;

  //Estimated process noise covariance
  const boost::numeric::ublas::matrix<double> m_process_noise_estimate;

  //Real process noise
  const boost::numeric::ublas::vector<double> m_process_noise_real;

  //State transition matrix, the effect of the current state on the next
  const boost::numeric::ublas::matrix<double> m_state_transition;

  ///The updated error estimation covariances (in the end of each timestep)
  std::vector<boost::numeric::ublas::matrix<double> > m_updated_covariances;

  ///The updated state (in the end of each timestep)
  std::vector<boost::numeric::ublas::vector<double> > m_updated_states;

  static const std::vector<boost::numeric::ublas::vector<double> > ParseInput(
    const std::vector<std::string>& input,
    const int n_timesteps);

  //static const boost::numeric::ublas::matrix<double> ParseInput(
  //  const std::vector<std::string>& input,
  //  const int n_timesteps);
};

#endif // MAINDIALOG_H

 

 

 

 

 

maindialog.cpp

 

#ifdef _WIN32
#undef __STRICT_ANSI__
#endif

#include "maindialog.h"

#include <vector>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/numeric/ublas/functional.hpp>

#include "fparser.hh"

#include "kalmanfilter.h"
#include "matrix.h"
//#include "trace.h"
#include "whitenoisesystem.h"

MainDialog::MainDialog(
  const int time,
  const boost::numeric::ublas::matrix<double>& control,
  const std::vector<std::string>& input,
  const boost::numeric::ublas::matrix<double>& measurement_noise_estimate,
  const boost::numeric::ublas::matrix<double>& observation,
  const boost::numeric::ublas::matrix<double>& init_covariance_estimate,
  const boost::numeric::ublas::matrix<double>& process_noise_estimate,
  const boost::numeric::ublas::matrix<double>& state_transition,
  const boost::numeric::ublas::vector<double>& init_state_real,
  const boost::numeric::ublas::vector<double>& process_noise_real,
  const std::vector<std::string>& state_names,
  const boost::numeric::ublas::vector<double>& init_state_estimate,
  const boost::numeric::ublas::vector<double>& measurement_noise_real)
  : m_control(control),
    m_init_covariance_estimate(init_covariance_estimate),
    m_init_state_estimate(init_state_estimate),
    m_init_state_real(init_state_real),
    m_inputs(ParseInput(input,time))
//    m_measurement_noise_estimate(measurement_noise_estimate),
//    m_measurement_noise_real(measurement_noise_real),
//    m_observation(observation),
//    m_process_noise_estimate(process_noise_estimate),
//    m_process_noise_real(process_noise_real),
//    m_state_transition(state_transition)
{
  Matrix::Test();
  //TRACE_FUNC();
  assert(state_names.size() == init_state_real.size());

  using boost::numeric::ublas::matrix;
  using boost::numeric::ublas::matrix_column;
  using boost::numeric::ublas::matrix_range;
  using boost::numeric::ublas::matrix_row;
  using boost::numeric::ublas::range;
  using boost::numeric::ublas::vector;
  const int n_states = init_state_real.size();

  //The resulting matrix, has time rows and states * three (real,measured,Kalman) columns
  matrix<double> data(time,n_states * m_n_curves_per_plot);
  assert(time == boost::numeric_cast<int>(data.size1()));
  assert(n_states * m_n_curves_per_plot == boost::numeric_cast<int>(data.size2()));
  assert(GetHeader(state_names).size() == data.size2());

  //const boost::numeric::ublas::matrix<double> inputs = ParseInput(input,time);
  const auto inputs = ParseInput(input,time);

  //TRACE_FUNC();
  WhiteNoiseSystem s(
    control,
    init_state_real,
    measurement_noise_real,
    process_noise_real,
    state_transition);

  //TRACE_FUNC();
  KalmanFilter k(
    control,
    init_state_estimate,
    init_covariance_estimate,
    measurement_noise_estimate,
    observation,process_noise_estimate,
    state_transition);

  //std::cout << "x_real,x_measured,x_Kalman,v_real,v_measured,v_Kalman,input\n";
  for (int i=0;i!=time;++i)
  {
    //TRACE(i);

    //Store the now-current states as the previous-states
    this->m_previous_state_estimates.push_back( k.GetStateEstimate() );
    this->m_previous_covariance_estimates.push_back( k.GetEstimationErrorCovariance() );

    //Update reality, that is, let the real system (i.e. reality) go to its next state
    assert(i < boost::numeric_cast<int>(inputs.size()));
    const vector<double>& input = inputs[i];

    s.GoToNextState(input);

    this->m_predicted_states.push_back( k.GetLastPredictedState() );
    this->m_predicted_covariances.push_back( k.GetLastPredictedCovariance() );

    //Perform a noisy measurement
    const vector<double> z_measured = s.Measure();
    m_measurements.push_back(z_measured);

    //Pass this measurement to the filter
    try
    {
      k.SupplyMeasurementAndInput(z_measured,input);

      m_innovations.push_back(k.GetLastInnovation());
      m_innovation_covariances.push_back(k.GetLastInnovationCovariance());
      m_kalman_gains.push_back(k.GetLastGain());
    }
    catch (std::runtime_error& e)
    {
      //Happens when innovation covariance becomes degenerate
      //(that is, its determinant is zero)
      m_data = data;
      return;
    }
    catch (...)
    {
      assert(!"Should never get here");
    }
    //Display what the filter predicts
    const vector<double> x_est_last = k.GetStateEstimate();
    for (int j=0; j!=n_states; ++j)
    {
      assert(i < boost::numeric_cast<int>(data.size1()));
      assert((j*m_n_curves_per_plot)+3 < boost::numeric_cast<int>(data.size2()));
      assert(j < boost::numeric_cast<int>(s.PeekAtRealState().size()));
      assert(j < boost::numeric_cast<int>(z_measured.size()));
      assert(j < boost::numeric_cast<int>(x_est_last.size()));
      assert(j < boost::numeric_cast<int>(input.size()));
      data(i,(j*m_n_curves_per_plot)+0) = s.PeekAtRealState()(j);
      data(i,(j*m_n_curves_per_plot)+1) = z_measured(j);
      data(i,(j*m_n_curves_per_plot)+2) = x_est_last(j);
      data(i,(j*m_n_curves_per_plot)+3) = input(j);
    }
    this->m_updated_states.push_back( k.GetLastUpdatedState() );
    this->m_updated_covariances.push_back( k.GetLastUpdatedCovariance() );

  }
  m_data = data;

  assert(time == boost::numeric_cast<int>(m_previous_state_estimates.size()));
  assert(time == boost::numeric_cast<int>(m_previous_covariance_estimates.size()));
  assert(time == boost::numeric_cast<int>(m_data.size1()));
  assert(time == boost::numeric_cast<int>(m_innovations.size()));
  assert(time == boost::numeric_cast<int>(m_innovation_covariances.size()));
  assert(time == boost::numeric_cast<int>(m_kalman_gains.size()));
  assert(time == boost::numeric_cast<int>(m_measurements.size()));
  assert(time == boost::numeric_cast<int>(m_predicted_states.size()));
  assert(time == boost::numeric_cast<int>(m_predicted_covariances.size()));
  assert(time == boost::numeric_cast<int>(m_updated_covariances.size()));
  assert(time == boost::numeric_cast<int>(m_updated_states.size()));
}

const boost::numeric::ublas::vector<std::string> MainDialog::GetHeader(
  const std::vector<std::string>& state_names)
{
  const int n_states = boost::numeric_cast<int>(state_names.size());
  boost::numeric::ublas::vector<std::string> v(n_states * m_n_curves_per_plot);
  for (int i=0; i!=n_states; ++i)
  {
    assert((i*m_n_curves_per_plot)+3 < boost::numeric_cast<int>(v.size()));
    assert(i < boost::numeric_cast<int>(state_names.size()));
    v((i*m_n_curves_per_plot)+0) = state_names[i] + "_real";
    v((i*m_n_curves_per_plot)+1) = state_names[i] + "_measured";
    v((i*m_n_curves_per_plot)+2) = state_names[i] + "_Kalman";
    v((i*m_n_curves_per_plot)+3) = state_names[i] + "_input";
  }
  assert(boost::numeric_cast<int>(state_names.size()) * m_n_curves_per_plot == boost::numeric_cast<int>(v.size()));
  return v;
}

const std::vector<boost::numeric::ublas::vector<double> > MainDialog::ParseInput(
  const std::vector<std::string>& input,
  const int n_timesteps)
{
  const int n_rows = n_timesteps;
  const int n_cols = input.size();
  std::vector<boost::numeric::ublas::vector<double> > m(n_rows,
    boost::numeric::ublas::vector<double>(n_cols));

  for (int row=0; row!=n_rows; ++row)
  {
    for (int col=0; col!=n_cols; ++col)
    {
      assert(col < boost::numeric_cast<int>(input.size()));
      const std::string& s = input[col];
      FunctionParser f;
      f.Parse(s.empty() ? "0.0" : s, "t");
      const double x = boost::numeric_cast<double>(row);
      const double xs[1] = { x };
      const double y = f.Eval(xs);
      assert(row < boost::numeric_cast<int>(m.size()));
      assert(col < boost::numeric_cast<int>(m[row].size()));
      m[row](col) = y;
    }
  }
  assert(n_timesteps == boost::numeric_cast<int>(m.size()));
  assert(!m.empty());
  assert(input.size() == m[0].size());
  return m;

}

/*
const boost::numeric::ublas::matrix<double> MainDialog::ParseInput(
  const std::vector<std::string>& input,
  const int n_timesteps)
{
  const int n_rows = input.size();
  const int n_cols = n_timesteps;
  boost::numeric::ublas::matrix<double> m(n_rows,n_cols);

  for (int row=0; row!=n_rows; ++row)
  {
    const std::string& s = input[row];
    FunctionParser f;
    f.Parse(s.empty() ? "0.0" : s, "t");
    for (int col=0; col!=n_cols; ++col)
    {
      const double x = boost::numeric_cast<double>(col);
      const double xs[1] = { x };
      const double y = f.Eval(xs);
      m(row,col) = y;
    }
  }
  return m;
}
*/

 

 

 

 

 

qtkalmanfilteralgorithmdialog.h

 

#ifndef QTKALMANFILTERALGORITHMDIALOG_H
#define QTKALMANFILTERALGORITHMDIALOG_H

#ifdef _WIN32
#undef __STRICT_ANSI__
#endif

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <QDialog>

namespace Ui {
  class QtKalmanFilterAlgorithmDialog;
}

struct QTableWidget;

class QtKalmanFilterAlgorithmDialog : public QDialog
{
  Q_OBJECT
  
public:
  explicit QtKalmanFilterAlgorithmDialog(QWidget *parent = 0);
  ~QtKalmanFilterAlgorithmDialog();

  void SetControl(const boost::numeric::ublas::matrix<double>& m);
  void SetKalmanGain(const boost::numeric::ublas::matrix<double>& m);
  void SetIdentityMatrix(const int sz);
  void SetInnovation(const boost::numeric::ublas::vector<double>& m);
  void SetInnovationCovariance(const boost::numeric::ublas::matrix<double>& m);
  void SetInput(const boost::numeric::ublas::vector<double>& m);
  void SetMeasurement(const boost::numeric::ublas::vector<double>& m);
  void SetMeasurementNoiseEstimate(const boost::numeric::ublas::matrix<double>& m);
  void SetObservation(const boost::numeric::ublas::matrix<double>& m);
  void SetPredictedCovariance(const boost::numeric::ublas::matrix<double>& m);
  void SetPredictedState(const boost::numeric::ublas::vector<double>& m);

  void SetPreviousCovarianceEstimate(const boost::numeric::ublas::matrix<double>& m);
  void SetPreviousStateEstimate(const boost::numeric::ublas::vector<double>& m);

  void SetProcessNoiseEstimate(const boost::numeric::ublas::matrix<double>& m);
  void SetStateNames(const std::vector<std::string>& names);
  void SetStateTransition(const boost::numeric::ublas::matrix<double>& m);
  void SetTime(const int i);
  void SetUpdatedCovariance(const boost::numeric::ublas::matrix<double>& m);
  void SetUpdatedState(const boost::numeric::ublas::vector<double>& m);

  
private:
  Ui::QtKalmanFilterAlgorithmDialog *ui;

  const std::vector<QTableWidget *> CollectMatrices() const;
  const std::vector<QTableWidget *> CollectVectors() const;

};

#endif // QTKALMANFILTERALGORITHMDIALOG_H

 

 

 

 

 

qtkalmanfilteralgorithmdialog.cpp

 

#ifdef _WIN32
#undef __STRICT_ANSI__
#endif

#include "qtkalmanfilteralgorithmdialog.h"

#include <boost/lexical_cast.hpp>

#include "matrix.h"
#include "qtmatrix.h"
#include "ui_qtkalmanfilteralgorithmdialog.h"

QtKalmanFilterAlgorithmDialog::QtKalmanFilterAlgorithmDialog(QWidget *parent) :
  QDialog(parent),
  ui(new Ui::QtKalmanFilterAlgorithmDialog)
{
  ui->setupUi(this);


  this->setStyleSheet(
   "QWidget#widget_1 { "
    "  background-color: qlineargradient(x1: 0, y1: 1, x2: 1, y2: 0, stop: 0 #fbb, stop: 1 #fff);"
    "} "
   "QWidget#widget_2 { "
    "  background-color: qlineargradient(x1: 0, y1: 1, x2: 1, y2: 0, stop: 0 #ffb, stop: 1 #fff);"
    "} "
   "QWidget#widget_3 { "
    "  background-color: qlineargradient(x1: 0, y1: 1, x2: 1, y2: 0, stop: 0 #bfb, stop: 1 #fff);"
    "} "
   "QWidget#widget_4 { "
    "  background-color: qlineargradient(x1: 0, y1: 1, x2: 1, y2: 0, stop: 0 #bff, stop: 1 #fff);"
    "} "
   "QWidget#widget_5 { "
    "  background-color: qlineargradient(x1: 0, y1: 1, x2: 1, y2: 0, stop: 0 #bbf, stop: 1 #fff);"
    "} "
   "QWidget#widget_6 { "
    "  background-color: qlineargradient(x1: 0, y1: 1, x2: 1, y2: 0, stop: 0 #fbf, stop: 1 #fff);"
    "} "
   "QWidget#widget_7 { "
    "  background-color: qlineargradient(x1: 0, y1: 1, x2: 1, y2: 0, stop: 0 #fff, stop: 1 #fff);"
    "} "
  );
}

QtKalmanFilterAlgorithmDialog::~QtKalmanFilterAlgorithmDialog()
{
  delete ui;
}

const std::vector<QTableWidget *> QtKalmanFilterAlgorithmDialog::CollectMatrices() const
{
  std::vector<QTableWidget *> v;
  v.push_back(ui->table_control_1);
  v.push_back(ui->table_covariance_predicted_2);
  v.push_back(ui->table_covariance_predicted_4);
  v.push_back(ui->table_covariance_predicted_5);
  v.push_back(ui->table_covariance_predicted_7);
  v.push_back(ui->table_estimated_measurement_noise);
  v.push_back(ui->table_estimated_process_noise);
  v.push_back(ui->table_identity_matrix);
  v.push_back(ui->table_innovation_covariance_4);
  v.push_back(ui->table_innovation_covariance_5_inverted);
  v.push_back(ui->table_kalman_gain_5);
  v.push_back(ui->table_kalman_gain_6);
  v.push_back(ui->table_kalman_gain_7);
  v.push_back(ui->table_new_covariance);
  v.push_back(ui->table_observation_3);
  v.push_back(ui->table_observation_4);
  v.push_back(ui->table_observation_4_transposed);
  v.push_back(ui->table_observation_5_transposed);
  v.push_back(ui->table_observation_7);
  v.push_back(ui->table_previous_covariance_estimate);
  v.push_back(ui->table_state_transition_1);
  v.push_back(ui->table_state_transition_1_2);
  v.push_back(ui->table_state_transition_2_transposed);
  return v;
}

const std::vector<QTableWidget *> QtKalmanFilterAlgorithmDialog::CollectVectors() const
{
  std::vector<QTableWidget *> v;
  v.push_back(ui->table_innovation_3);
  v.push_back(ui->table_innovation_6);
  v.push_back(ui->table_input);
  v.push_back(ui->table_measurement);
  v.push_back(ui->table_new_state_estimate);
  v.push_back(ui->table_previous_state_estimate);
  v.push_back(ui->table_state_predicted_1);
  v.push_back(ui->table_state_predicted_3);
  v.push_back(ui->table_state_predicted_6);
  return v;
}

void QtKalmanFilterAlgorithmDialog::SetControl(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_control_1);
}

void QtKalmanFilterAlgorithmDialog::SetIdentityMatrix(const int sz)
{
  QtMatrix::MatrixToTable(
    boost::numeric::ublas::identity_matrix<double>(sz),
    ui->table_identity_matrix);
}

void QtKalmanFilterAlgorithmDialog::SetInnovation(const boost::numeric::ublas::vector<double>& m)
{
  QtMatrix::VectorToTable(m,ui->table_innovation_3);
  QtMatrix::VectorToTable(m,ui->table_innovation_6);
}

void QtKalmanFilterAlgorithmDialog::SetInnovationCovariance(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_innovation_covariance_4);
  QtMatrix::MatrixToTable(
    Matrix::Inverse(m),
    ui->table_innovation_covariance_5_inverted);
}

void QtKalmanFilterAlgorithmDialog::SetInput(const boost::numeric::ublas::vector<double>& m)
{
  QtMatrix::VectorToTable(m,ui->table_input);
}

void QtKalmanFilterAlgorithmDialog::SetKalmanGain(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_kalman_gain_5);
  QtMatrix::MatrixToTable(m,ui->table_kalman_gain_6);
  QtMatrix::MatrixToTable(m,ui->table_kalman_gain_7);
}

void QtKalmanFilterAlgorithmDialog::SetMeasurement(const boost::numeric::ublas::vector<double>& m)
{
  QtMatrix::VectorToTable(m,ui->table_measurement);
}


void QtKalmanFilterAlgorithmDialog::SetMeasurementNoiseEstimate(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_estimated_measurement_noise);
}

void QtKalmanFilterAlgorithmDialog::SetObservation(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_observation_3);
  QtMatrix::MatrixToTable(m,ui->table_observation_4);
  QtMatrix::MatrixToTable(
    boost::numeric::ublas::trans(m),
    ui->table_observation_4_transposed);
  QtMatrix::MatrixToTable(
    boost::numeric::ublas::trans(m),
    ui->table_observation_5_transposed);
  QtMatrix::MatrixToTable(m,ui->table_observation_7);
}

void QtKalmanFilterAlgorithmDialog::SetPredictedCovariance(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_covariance_predicted_2);
  QtMatrix::MatrixToTable(m,ui->table_covariance_predicted_4);
  QtMatrix::MatrixToTable(m,ui->table_covariance_predicted_5);
  QtMatrix::MatrixToTable(m,ui->table_covariance_predicted_7);
}

void QtKalmanFilterAlgorithmDialog::SetPredictedState(const boost::numeric::ublas::vector<double>& m)
{
  QtMatrix::VectorToTable(m,ui->table_state_predicted_1);
  QtMatrix::VectorToTable(m,ui->table_state_predicted_3);
  QtMatrix::VectorToTable(m,ui->table_state_predicted_6);
}

void QtKalmanFilterAlgorithmDialog::SetPreviousCovarianceEstimate(
  const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_previous_covariance_estimate);
}

void QtKalmanFilterAlgorithmDialog::SetPreviousStateEstimate(
  const boost::numeric::ublas::vector<double>& m)
{
  QtMatrix::VectorToTable(m,ui->table_previous_state_estimate);
}


void QtKalmanFilterAlgorithmDialog::SetProcessNoiseEstimate(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_estimated_process_noise);
}

void QtKalmanFilterAlgorithmDialog::SetStateNames(const std::vector<std::string>& names)
{
  const int n = boost::numeric_cast<int>(names.size());
  //Matrices
  {
    const std::vector<QTableWidget *> v = CollectMatrices();
    const std::size_t sz = v.size();
    for (std::size_t i = 0; i!=sz; ++i)
    {
      QTableWidget * const table = v[i];
      assert(table);
      table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
      table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

      table->setColumnCount(boost::numeric_cast<int>(names.size()));
      table->setRowCount(boost::numeric_cast<int>(names.size()));
      assert(table->columnCount() == boost::numeric_cast<int>(names.size()));
      assert(table->rowCount() == boost::numeric_cast<int>(names.size()));
      for (int j = 0; j!=n; ++j)
      {
        {
          QTableWidgetItem * const item = new QTableWidgetItem;
          item->setText(names[j].c_str());
          table->setVerticalHeaderItem(j,item);
        }
        {
          QTableWidgetItem * const item = new QTableWidgetItem;
          item->setText(names[j].c_str());
          table->setHorizontalHeaderItem(j,item);
        }
      }
      table->resizeColumnsToContents();
      table->resizeRowsToContents();
      table->update();
      table->setFixedHeight(
        table->verticalHeader()->length()   + 2 + table->horizontalHeader()->height());
      //table->setFixedSize(
      //  table->horizontalHeader()->length() + 2 + table->verticalHeader()->width(),
      //  table->verticalHeader()->length()   + 2 + table->horizontalHeader()->height());
    }
  }
  //Vectors
  {
    const std::vector<QTableWidget *> v = CollectVectors();

    const std::size_t sz = v.size();
    for (std::size_t i = 0; i!=sz; ++i)
    {
      QTableWidget * const table = v[i];
      table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
      table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

      table->setRowCount(boost::numeric_cast<int>(names.size()));
      assert(table->rowCount() == boost::numeric_cast<int>(names.size()));
      //Remove top text
      {
        QTableWidgetItem * const item = new QTableWidgetItem;
        item->setText(" ");
        table->setHorizontalHeaderItem(0,item);
      }

      for (int j = 0; j!=n; ++j)
      {
        QTableWidgetItem * const item = new QTableWidgetItem;
        item->setText(names[j].c_str());
        table->setVerticalHeaderItem(j,item);
      }
      table->resizeColumnsToContents();
      table->resizeRowsToContents();
      table->setFixedHeight(
        table->verticalHeader()->length()   + 2 + table->horizontalHeader()->height());
      //table->setFixedSize(
      //  table->horizontalHeader()->length() + 2 + table->verticalHeader()->width(),
      //  table->verticalHeader()->length()   + 2 + table->horizontalHeader()->height());
    }
  }
}

void QtKalmanFilterAlgorithmDialog::SetStateTransition(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_state_transition_1);
  QtMatrix::MatrixToTable(m,ui->table_state_transition_1_2);
  QtMatrix::MatrixToTable(
    boost::numeric::ublas::trans(m),
    ui->table_state_transition_2_transposed);
}

void QtKalmanFilterAlgorithmDialog::SetTime(const int i)
{
  const std::string s = "Time: " + boost::lexical_cast<std::string>(i);
  ui->label_time->setText(s.c_str());
}

void QtKalmanFilterAlgorithmDialog::SetUpdatedCovariance(const boost::numeric::ublas::matrix<double>& m)
{
  QtMatrix::MatrixToTable(m,ui->table_new_covariance);

}

void QtKalmanFilterAlgorithmDialog::SetUpdatedState(const boost::numeric::ublas::vector<double>& m)
{
  QtMatrix::VectorToTable(m,ui->table_new_state_estimate);
}

 

 

 

 

 

qtmain.cpp

 

#ifdef _WIN32
#undef __STRICT_ANSI__
#endif

#include <QtGui/QApplication>
#include "qtmaindialog.h"
#include "trace.h"

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  START_TRACE();
  QtMainDialog w;
  w.show();
  return a.exec();
}

 

 

 

 

 

qtmaindialog.h

 

#ifndef QTMAINDIALOG_H
#define QTMAINDIALOG_H

#ifdef _WIN32
#undef __STRICT_ANSI__
#endif

#include <vector>

#include <QDialog>

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>

namespace Ui {
  class QtMainDialog;
}

struct QwtPlot;
struct QwtPlotCurve;
struct QTableWidget;

class QtMainDialog : public QDialog
{
  Q_OBJECT
  
public:
  explicit QtMainDialog(QWidget *parent = 0);
  ~QtMainDialog();
  
private:
  Ui::QtMainDialog *ui;

  std::vector<QwtPlotCurve *> m_curves;
  std::vector<QwtPlot *> m_plots;

  ///Execute the simulation
  void DoSim();

  ///Create a timeseries of the input function
  //static const boost::numeric::ublas::matrix<double> ParseInput(const QTableWidget * const table, const int time);

  ///Set the number of states, so that the GUI elements can update themselves to this number
  void SetStateSize(const int n);


  void UpdateLegends();

private slots:
  void on_box_n_states_valueChanged(int arg1);
  const std::vector<std::string> GetLegend() const;
  const std::vector<QTableWidget *> CollectMatrices() const;
  const std::vector<QTableWidget *> CollectVectors() const;
  void on_button_1_clicked();
  void on_button_2_clicked();
  void on_button_3_clicked();
  void on_button_4_clicked();
  void on_button_start_clicked();
  void on_button_5_clicked();
};

#endif // QTMAINDIALOG_H

 

 

 

 

 

qtmaindialog.cpp

 

#ifdef _WIN32
#undef __STRICT_ANSI__
#endif

#include "qtmaindialog.h"

#include <cassert>
#include <cstdlib>

#include <boost/lexical_cast.hpp>
#include <boost/numeric/ublas/functional.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>

#include <QVBoxLayout>

#include "qwt_legend.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_grid.h"
#include "qwt_plot_zoomer.h"


#include "maindialog.h"
#include "matrix.h"
#include "qtmatrix.h"
#include "qtkalmanfilteralgorithmdialog.h"
#include "ui_qtmaindialog.h"

const std::vector<std::vector<double> > To2dVector(const boost::numeric::ublas::matrix<double>& m)
{
  const std::size_t n_rows = m.size1();
  const std::size_t n_cols = m.size2();
  std::vector<std::vector<double> > v(n_cols,std::vector<double>(n_rows,0.0));
  for (std::size_t row = 0; row!=n_rows; ++row)
  {
    for (std::size_t col = 0; col!=n_cols; ++col)
    {
      assert(row < m.size1());
      assert(col < m.size2());
      v[col][row] = m(row,col);
    }
  }
  return v;
}


QtMainDialog::QtMainDialog(QWidget *parent)
  : QDialog(parent),
    ui(new Ui::QtMainDialog)
{
  ui->setupUi(this);

  //{
  //  assert(ui->scroll_area_algorithm_layout->layout());
  //  QtKalmanFilterAlgorithmDialog * const d = new QtKalmanFilterAlgorithmDialog;
  //  assert(d);
  //  ui->scroll_area_algorithm_layout->layout()->addWidget(d);
  //}

  this->SetStateSize(ui->box_n_states->value());
  ui->button_2->click();
}

QtMainDialog::~QtMainDialog()
{
  {
    const std::size_t sz = m_curves.size();
    for (std::size_t i=0; i!=sz; ++i) delete m_curves[i];
  }
  {
    const std::size_t sz = m_plots.size();
    for (std::size_t i=0; i!=sz; ++i) delete m_plots[i];
  }
  delete ui;
}

const std::vector<QTableWidget *> QtMainDialog::CollectMatrices() const
{
  std::vector<QTableWidget *> v;
  v.push_back(ui->table_control);
  v.push_back(ui->table_init_covariance_estimate);
  v.push_back(ui->table_measurement_noise_estimate);
  v.push_back(ui->table_observation);
  v.push_back(ui->table_process_noise_covariance_estimate);
  v.push_back(ui->table_state_transition);
  return v;
}

const std::vector<QTableWidget *> QtMainDialog::CollectVectors() const
{
  std::vector<QTableWidget *> v;
  v.push_back(ui->table_init_state_estimate);
  v.push_back(ui->table_init_state_real);
  v.push_back(ui->table_input);
  v.push_back(ui->table_real_measurement_noise);
  v.push_back(ui->table_real_process_noise);
  v.push_back(ui->table_states);
  return v;
}

void QtMainDialog::DoSim()
{
  const int n_curves_per_plot = MainDialog::m_n_curves_per_plot;
  assert(boost::numeric_cast<int>(m_curves.size()) == n_curves_per_plot * boost::numeric_cast<int>(m_plots.size()));
  try
  {
    //Do the sim
    const int n_timesteps_desired = ui->box_n_timesteps->value();
    const boost::numeric::ublas::vector<double> init_x_real = QtMatrix::ToVector(ui->table_init_state_real);
    const std::vector<std::string> input = QtMatrix::ToStrVector(ui->table_input);
    const boost::numeric::ublas::vector<double> x_real_measurement_noise = QtMatrix::ToVector(ui->table_real_measurement_noise);
    const boost::numeric::ublas::vector<double> x_first_guess = QtMatrix::ToVector(ui->table_init_state_estimate);
    const boost::numeric::ublas::matrix<double> p_first_guess = QtMatrix::ToMatrix(ui->table_init_covariance_estimate);
    const boost::numeric::ublas::matrix<double> control = QtMatrix::ToMatrix(ui->table_control);
    const boost::numeric::ublas::matrix<double> measurement_noise_estimate = QtMatrix::ToMatrix(ui->table_measurement_noise_estimate);
    const boost::numeric::ublas::matrix<double> observation = QtMatrix::ToMatrix(ui->table_observation);
    const boost::numeric::ublas::vector<double> process_noise_real = QtMatrix::ToVector(ui->table_real_process_noise);
    const boost::numeric::ublas::matrix<double> process_noise_estimate = QtMatrix::ToMatrix(ui->table_process_noise_covariance_estimate);
    const boost::numeric::ublas::matrix<double> state_transition = QtMatrix::ToMatrix(ui->table_state_transition);
    const std::vector<std::string> state_names = GetLegend();
    assert(state_names.size() == init_x_real.size());
    const MainDialog d(
      n_timesteps_desired,
      control,
      input,
      measurement_noise_estimate,
      observation,
      p_first_guess,
      process_noise_estimate,
      state_transition,
      init_x_real,
      process_noise_real,
      state_names,
      x_first_guess,
      x_real_measurement_noise);

    //Display data as graph
    {
      //Convert data to a collection of std::vector, for QwtPlot to read
      const boost::numeric::ublas::matrix<double>& data = d.GetData();
      //n_timesteps may differ from n_timesteps_desired, because in the actual simulation
      //the innovation variance may become degenerate
      const int n_timesteps = data.size1(); //Number of rows
      const std::vector<std::vector<double> > vs = To2dVector(data);

      //Create time series
      std::vector<double> time_series(n_timesteps,0.0);
      for (int t=0; t!=n_timesteps; ++t) time_series[t] = boost::numeric_cast<double>(t);

      //Put data on curves
      assert(vs.size() == m_curves.size()); //-1 as the curves also plot the input
      assert(n_timesteps_desired == boost::numeric_cast<int>(vs[0].size()));
      assert(n_timesteps_desired == boost::numeric_cast<int>(time_series.size()));
      const std::size_t n_curves = m_curves.size();
      for (std::size_t i=0; i!=n_curves; ++i)
      {
        const std::vector<double>& v = vs[i];
        assert(n_timesteps_desired == boost::numeric_cast<int>(v.size()));
        #ifdef _WIN32
        m_curves[i]->setData(new QwtPointArrayData(&time_series[0],&v[0],time_series.size()));
        #else
        m_curves[i]->setData(&time_series[0],&v[0],time_series.size());
        #endif
      }

      //Put curves in the plots
      const std::size_t n_plots = m_plots.size();
      for (std::size_t i=0; i!=n_plots; ++i)
      {
        m_plots[i]->setAxisScale(QwtPlot::xBottom,0.0,n_timesteps);
        const std::vector<double> min_values
          = {
            *std::min_element(vs[(i*n_curves_per_plot)+0].begin(),vs[(i*n_curves_per_plot)+0].end()),
            *std::min_element(vs[(i*n_curves_per_plot)+1].begin(),vs[(i*n_curves_per_plot)+1].end()),
            *std::min_element(vs[(i*n_curves_per_plot)+2].begin(),vs[(i*n_curves_per_plot)+2].end()),
            *std::min_element(vs[(i*n_curves_per_plot)+3].begin(),vs[(i*n_curves_per_plot)+3].end())
          };
        const double min_value = *std::min_element(min_values.begin(),min_values.end());
        const std::vector<double> max_values
          = {
            *std::max_element(vs[(i*n_curves_per_plot)+0].begin(),vs[(i*n_curves_per_plot)+0].end()),
            *std::max_element(vs[(i*n_curves_per_plot)+1].begin(),vs[(i*n_curves_per_plot)+1].end()),
            *std::max_element(vs[(i*n_curves_per_plot)+2].begin(),vs[(i*n_curves_per_plot)+2].end()),
            *std::max_element(vs[(i*n_curves_per_plot)+3].begin(),vs[(i*n_curves_per_plot)+3].end())
          };
        const double max_value = *std::max_element(max_values.begin(),max_values.end());
        m_plots[i]->setAxisScale(
          QwtPlot::yLeft,
          std::abs(min_value - max_value) < 0.01 ? 0.0 : min_value,
          std::abs(min_value - max_value) < 0.01 ? 1.0 : max_value
        );
        m_plots[i]->replot();
      }
    }



    //Display data as algorithm
    {
      //Convert data to a collection of std::vector, for QwtPlot to read
      const boost::numeric::ublas::matrix<double>& data = d.GetData();
      //n_timesteps may differ from n_timesteps_desired, because in the actual simulation
      //the innovation variance may become degenerate
      const int n_timesteps = data.size1(); //Number of rows

      //Remove previous dialogs
      delete ui->scroll_area_algorithm_layout->layout();
      ui->scroll_area_algorithm_layout->setLayout(new QVBoxLayout);
      assert(ui->scroll_area_algorithm_layout->layout());

      for (int i=0; i!=n_timesteps; ++i)
      {
        QtKalmanFilterAlgorithmDialog * const qtdialog = new QtKalmanFilterAlgorithmDialog;
        assert(qtdialog);
        assert(i < boost::numeric_cast<int>(d.GetInnovations().size()));
        assert(i < boost::numeric_cast<int>(d.GetInputs().size()));
        assert(i < boost::numeric_cast<int>(d.GetKalmanGains().size()));
        assert(i < boost::numeric_cast<int>(d.GetPredictedCovariances().size()));
        assert(i < boost::numeric_cast<int>(d.GetPredictedStates().size()));
        assert(i < boost::numeric_cast<int>(d.GetPreviousCovarianceEstimates().size()));
        assert(i < boost::numeric_cast<int>(d.GetPreviousStateEstimates().size()));
        assert(i < boost::numeric_cast<int>(d.GetUpdatedCovariances().size()));
        assert(i < boost::numeric_cast<int>(d.GetUpdatedStates().size()));
        std::string style_sheet = qtdialog->styleSheet().toStdString()
          + std::string("QDialog { background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 ");
        switch (i % 6)
        {
          case 0: style_sheet+= "#f00, stop: 1 #000); }"; break;
          case 1: style_sheet+= "#ff0, stop: 1 #000); }"; break;
          case 2: style_sheet+= "#0f0, stop: 1 #000); }"; break;
          case 3: style_sheet+= "#0ff, stop: 1 #000); }"; break;
          case 4: style_sheet+= "#f0f, stop: 1 #000); }"; break;
          case 5: style_sheet+= "#fff, stop: 1 #000); }"; break;
        }
        qtdialog->setStyleSheet(style_sheet.c_str());

        qtdialog->SetControl(control);
        qtdialog->SetKalmanGain(d.GetKalmanGains().at(i));
        qtdialog->SetIdentityMatrix(boost::numeric_cast<int>(state_names.size()));
        qtdialog->SetInnovation(d.GetInnovations().at(i));
        qtdialog->SetInnovationCovariance(d.GetInnovationCovariances().at(i));
        qtdialog->SetInput(d.GetInputs().at(i));
        qtdialog->SetMeasurement(d.GetMeasurements().at(i));
        qtdialog->SetMeasurementNoiseEstimate(measurement_noise_estimate);
        qtdialog->SetObservation(observation);
        qtdialog->SetPredictedCovariance(d.GetPredictedCovariances().at(i));
        qtdialog->SetPredictedState(d.GetPredictedStates().at(i));
        qtdialog->SetPreviousCovarianceEstimate(d.GetPreviousCovarianceEstimates().at(i));
        qtdialog->SetPreviousStateEstimate(d.GetPreviousStateEstimates().at(i));
        qtdialog->SetProcessNoiseEstimate(process_noise_estimate);
        qtdialog->SetStateNames(state_names);
        qtdialog->SetStateTransition(state_transition);
        qtdialog->SetTime(i);
        qtdialog->SetUpdatedCovariance(d.GetUpdatedCovariances().at(i));
        qtdialog->SetUpdatedState(d.GetUpdatedStates().at(i));
        assert(ui->scroll_area_algorithm);
        assert(ui->scroll_area_algorithm_layout->layout());
        ui->scroll_area_algorithm_layout->layout()->addWidget(qtdialog);
      }
    }
  }
  catch (boost::bad_lexical_cast&)
  {
    //User input is invalid
    //For example 'Hello' instead of a double
    const std::vector<double> v(1,0.0);
    {
      const std::size_t sz = m_curves.size();
      for (std::size_t i=0; i!=sz; ++i)
      {
        #ifdef _WIN32
        m_curves[i]->setData(new QwtPointArrayData(&v[0],&v[0],v.size()));
        #else
        m_curves[i]->setData(&v[0],&v[0],v.size());
        #endif
      }
    }
    {
      const std::size_t sz = m_plots.size();
      for (std::size_t i=0; i!=sz; ++i)
      {
        m_plots[i]->replot();
      }
    }
  }
  catch(...)
  {
    assert(!"Should never get here");
  }
}

const std::vector<std::string> QtMainDialog::GetLegend() const
{
  std::vector<std::string> v;
  const int sz = ui->table_states->rowCount();
  for (int i=0; i!=sz; ++i)
  {
    const QTableWidgetItem * const item = ui->table_states->item(i,0);
    const std::string s = item ? item->text().toStdString() : "?";
    v.push_back(s);
  }
  return v;
}



void QtMainDialog::on_box_n_states_valueChanged(int arg1)
{
  this->SetStateSize(arg1);
}

void QtMainDialog::on_button_1_clicked()
{
  ui->box_n_states->setValue(1);
  //Set the variables here
  //Use examples and variables as http://greg.czerniak.info/guides/kalman1
  //Context: measuring a voltage
  ui->table_control->setItem(0,0,new QTableWidgetItem("0.0"));
  ui->table_init_covariance_estimate->setItem(0,0,new QTableWidgetItem("1.0"));
  ui->table_init_state_estimate->setItem(0,0,new QTableWidgetItem("3.0"));
  ui->table_init_state_real->setItem(0,0,new QTableWidgetItem("1.25"));
  ui->table_input->setItem(0,0,new QTableWidgetItem("0.0"));
  ui->table_measurement_noise_estimate->setItem(0,0,new QTableWidgetItem("0.1"));
  ui->table_observation->setItem(0,0,new QTableWidgetItem("1.0"));
  ui->table_process_noise_covariance_estimate->setItem(0,0,new QTableWidgetItem("0.0001"));
  ui->table_real_measurement_noise->setItem(0,0,new QTableWidgetItem("0.1"));
  ui->table_real_process_noise->setItem(0,0,new QTableWidgetItem("0.00001"));
  ui->table_states->setItem(0,0,new QTableWidgetItem("V"));
  ui->table_state_transition->setItem(0,0,new QTableWidgetItem("1.0"));
  UpdateLegends();
  DoSim();
}

void QtMainDialog::on_button_2_clicked()
{
  const int n = 2;
  ui->box_n_states->setValue(n);
  //Set the variables here
  //Use example from Simon, D. Kalman Filtering. Embedded Systems Programming. June 2001
  const double acceleration = 1.0;
  const double measurement_noise = 10.0; //Called 'measnoise'
  const double accelnoise = 0.2; //Called 'accelnoise'
  const double dt = 0.1; //Timestep

  {
    //A gas pedal only influences speed
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n, { 0.0,0.0,0.0,dt } );
    QtMatrix::MatrixToTable(m,ui->table_control);
  }
  {
    //Just a guess
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n, { 1.0,0.0,0.0,1.0 } );
    QtMatrix::MatrixToTable(m,ui->table_init_covariance_estimate);
  }
  {
    //Initial state estimates are a bit off on purpose
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 10.0,1.0 } );
    QtMatrix::VectorToTable(v,ui->table_init_state_estimate);
  }

  {
    //From exact standstill
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.0,0.0 } );
    QtMatrix::VectorToTable(v,ui->table_init_state_real);
  }

  {
    //A gas pedal only influences speed
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.0,acceleration } );
    QtMatrix::VectorToTable(v,ui->table_input);
  }

  {
    //Only (pessimistic) normal noise in GPS, speedometer has enormous noise as if defect (yet cannot be 0.0)
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n, { 10.0 * measurement_noise,0.0,0.0,1000000.0 } );
    QtMatrix::MatrixToTable(m,ui->table_measurement_noise_estimate);
  }

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n, { 1.0,0.0,0.0,0.0 } ); //Only use GPS, no speedometer
    QtMatrix::MatrixToTable(m,ui->table_observation);
  }

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n, {
        10.0 * accelnoise,
        10.0 * accelnoise,
        10.0 * accelnoise,
        10.0 * accelnoise
      } ); //Pessimistic estimate
    QtMatrix::MatrixToTable(m,ui->table_process_noise_covariance_estimate);
  }

  {
    //Only normal noise in GPS, speedometer has enormous noise as if defect (yet cannot be 0.0)
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { measurement_noise, 1000000.0 } );
    QtMatrix::VectorToTable(v,ui->table_real_measurement_noise);
  }

  {
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.5  * accelnoise * dt * dt, accelnoise * dt} );
    QtMatrix::VectorToTable(v,ui->table_real_process_noise);
  }

  ui->table_states->setItem(0,0,new QTableWidgetItem("x"));
  ui->table_states->setItem(1,0,new QTableWidgetItem("v"));

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n, { 1.0, 0.0, dt, 1.0 } );
    QtMatrix::MatrixToTable(m,ui->table_state_transition);
  }
  UpdateLegends();
  DoSim();
}

void QtMainDialog::on_button_3_clicked()
{
  const int n = 4;
  ui->box_n_states->setValue(n);
  //Set the variables here
  //Use example from Simon, D. Kalman Filtering. Embedded Systems Programming. June 2001
  const double dt = 0.1; //Timestep
  const double g = 9.81; //Gravity
  const double angle = M_PI / 4.0; //Radians. 45 degrees = M_PI / 4.0 radians

  {
    //A gas pedal only influences speed
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          0.0, 0.0, 0.0, 0.0,
          0.0, 0.0, 0.0, 0.0,
          0.0, 0.0, 1.0, 0.0,
          0.0, 0.0, 0.0, 1.0
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_control);
  }
  {
    //Just a guess
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          1.0, 0.0, 0.0, 0.0,
          0.0, 1.0, 0.0, 0.0,
          0.0, 0.0, 1.0, 0.0,
          0.0, 0.0, 0.0, 1.0
        }
      );

    QtMatrix::MatrixToTable(m,ui->table_init_covariance_estimate);
  }
  {
    //Initial state estimates are a bit off on purpose
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.0, 100.0 * std::cos(angle), 500.0, 100.0 * sin(angle) } );
    QtMatrix::VectorToTable(v,ui->table_init_state_estimate);
  }

  {
    //From exact standstill
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.0, 100.0 * std::cos(angle), 0.0, 100.0 * sin(angle) } );
    QtMatrix::VectorToTable(v,ui->table_init_state_real);
  }

  {
    //Gravity influences position and velocity in the vertical direction
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.0,0.0,-0.5*g*dt*dt,-g*dt} );
    QtMatrix::VectorToTable(v,ui->table_input);
  }

  {

    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          0.2, 0.0, 0.0, 0.0,
          0.0, 0.2, 0.0, 0.0,
          0.0, 0.0, 0.2, 0.0,
          0.0, 0.0, 0.0, 0.2
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_measurement_noise_estimate);
  }

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          1.0, 0.0, 0.0, 0.0,
          0.0, 1.0, 0.0, 0.0,
          0.0, 0.0, 1.0, 0.0,
          0.0, 0.0, 0.0, 1.0
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_observation);
  }

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          0.0, 0.0, 0.0, 0.0,
          0.0, 0.0, 0.0, 0.0,
          0.0, 0.0, 0.0, 0.0,
          0.0, 0.0, 0.0, 0.0
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_process_noise_covariance_estimate);
  }

  {
    //Only normal noise in GPS, speedometer has enormous noise as if defect (yet cannot be 0.0)
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 30.0, 30.0, 30.0, 30.0 } );
    QtMatrix::VectorToTable(v,ui->table_real_measurement_noise);
  }

  {
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.0, 0.0, 0.0, 0.0 } );
    QtMatrix::VectorToTable(v,ui->table_real_process_noise);
  }

  ui->table_states->setItem(0,0,new QTableWidgetItem("x"));
  ui->table_states->setItem(1,0,new QTableWidgetItem("Vx"));
  ui->table_states->setItem(2,0,new QTableWidgetItem("y"));
  ui->table_states->setItem(3,0,new QTableWidgetItem("Vy"));

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        { //Beware: appears as transposition of real matrix
          1.0, 0.0, 0.0, 0.0,
           dt, 1.0, 0.0, 0.0,
          0.0, 0.0, 1.0, 0.0,
          0.0, 0.0, dt , 1.0
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_state_transition);
  }
  UpdateLegends();
  DoSim();
}

void QtMainDialog::on_button_4_clicked()
{
  const int n = 2;
  ui->box_n_states->setValue(n);
  //Set the variables here
  //Use spring system: a mass is lying on a frictionless surface and is connected to two horizontal springs
  const double dt = 0.1; //Timestep
  const double k = 1.0; //Spring constant
  const double mass = 1.0; //Mass

  {
    //No input used, so control matrix can be zeroes only
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          0.0, 0.0,
          0.0, 0.0
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_control);
  }
  {
    //Just a guess
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          1.0, 0.0,
          0.0, 1.0
        }
      );

    QtMatrix::MatrixToTable(m,ui->table_init_covariance_estimate);
  }
  {
    //Initial state estimates are a bit off on purpose
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { -10.0, -1.0 } );
    QtMatrix::VectorToTable(v,ui->table_init_state_estimate);
  }

  {
    //From a perfect standstill at a certain position
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 10.0, 0.0 } );
    QtMatrix::VectorToTable(v,ui->table_init_state_real);
  }

  {
    //There is no input supplied
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.0,0.0 } );
    QtMatrix::VectorToTable(v,ui->table_input);
  }

  {

    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          1.0, 0.0,
          0.0, 1.0
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_measurement_noise_estimate);
  }

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          1.0, 0.0,
          0.0, 0.0
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_observation);
  }

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        {
          2.0, 2.0,
          2.0, 2.0
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_process_noise_covariance_estimate);
  }

  {
    //Some noise
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 1.0, 1.0 } );
    QtMatrix::VectorToTable(v,ui->table_real_measurement_noise);
  }

  {
    //Simulation, so process noise is zero
    const boost::numeric::ublas::vector<double> v
      = Matrix::CreateVector( { 0.0, 0.0 } );
    QtMatrix::VectorToTable(v,ui->table_real_process_noise);
  }

  ui->table_states->setItem(0,0,new QTableWidgetItem("x"));
  ui->table_states->setItem(1,0,new QTableWidgetItem("v"));

  {
    const boost::numeric::ublas::matrix<double> m
      = Matrix::CreateMatrix(n,n,
        { //Beware: appears as transposition of real matrix
          1.0       ,   dt,
          -dt*k/mass, 0.99
        }
      );
    QtMatrix::MatrixToTable(m,ui->table_state_transition);
  }
  UpdateLegends();
  DoSim();
}

void QtMainDialog::on_button_5_clicked()
{
  ui->box_n_states->setValue(1);
  //Context: airhockey puck with a constant speed
  ui->table_control->setItem(0,0,new QTableWidgetItem("1.0"));
  ui->table_init_covariance_estimate->setItem(0,0,new QTableWidgetItem("0.0"));
  ui->table_init_state_estimate->setItem(0,0,new QTableWidgetItem("0.0"));
  ui->table_init_state_real->setItem(0,0,new QTableWidgetItem("0.0"));
  ui->table_input->setItem(0,0,new QTableWidgetItem("1.0"));
  ui->table_measurement_noise_estimate->setItem(0,0,new QTableWidgetItem("0.0000001"));
  ui->table_observation->setItem(0,0,new QTableWidgetItem("1.0"));
  ui->table_process_noise_covariance_estimate->setItem(0,0,new QTableWidgetItem("0.0"));
  ui->table_real_measurement_noise->setItem(0,0,new QTableWidgetItem("0.0"));
  ui->table_real_process_noise->setItem(0,0,new QTableWidgetItem("0.0"));
  ui->table_states->setItem(0,0,new QTableWidgetItem("x"));
  ui->table_state_transition->setItem(0,0,new QTableWidgetItem("1.0"));
  UpdateLegends();
  DoSim();
}

void QtMainDialog::SetStateSize(const int n)
{
  //Resize plots
  while (n > boost::numeric_cast<int>(m_plots.size()))
  {
    //Add new plots
    QwtPlot * const plot = new QwtPlot;
    plot->setAxisTitle(QwtPlot::xBottom,"Time");

    QwtPlotCurve * const curve_real = new QwtPlotCurve;
    curve_real->setTitle("Real");
    curve_real->attach(plot);
    curve_real->setStyle(QwtPlotCurve::Lines);
    curve_real->setPen(QPen(QColor(0,0,255)));

    QwtPlotCurve * const curve_measured = new QwtPlotCurve;
    curve_measured->setTitle("Measured");
    curve_measured->attach(plot);
    curve_measured->setStyle(QwtPlotCurve::Lines);
    curve_measured->setPen(QPen(QColor(0,255,0)));

    QwtPlotCurve * const curve_estimate = new QwtPlotCurve;
    curve_estimate->setTitle("Kalman estimate");
    curve_estimate->attach(plot);
    curve_estimate->setStyle(QwtPlotCurve::Lines);
    curve_estimate->setPen(QPen(QColor(255,0,0)));

    QwtPlotCurve * const curve_input = new QwtPlotCurve;
    curve_input->setTitle("Input");
    curve_input->attach(plot);
    curve_input->setStyle(QwtPlotCurve::Lines);
    curve_input->setPen(QPen(QColor(0,0,0)));
    m_curves.push_back(curve_real);
    m_curves.push_back(curve_measured);
    m_curves.push_back(curve_estimate);
    m_curves.push_back(curve_input);
    m_plots.push_back(plot);

    //Add grid
    { QwtPlotGrid * const grid = new QwtPlotGrid; grid->setPen(QPen(QColor(196,196,196))); grid->attach(plot); }
    //Add zoomer
    {
      new QwtPlotZoomer(plot->canvas());
    }
    {
      // legend
      QwtLegend * const legend = new QwtLegend;
      legend->setFrameStyle(QFrame::Box|QFrame::Sunken);
      plot->insertLegend(legend, QwtPlot::RightLegend);
    }
    ui->layout_plots->addWidget(plot);
  }

  while (n < boost::numeric_cast<int>(m_plots.size()))
  {
    //Delete superfluous plots
    ui->layout_plots->removeWidget(m_plots.back());
    delete m_plots.back();
    m_plots.pop_back();
    for (int i=0; i!=MainDialog::m_n_curves_per_plot; ++i)
    {
      //delete m_curves.back(); //Done by plot
      m_curves.pop_back();
    }
  }
  assert(n == boost::numeric_cast<int>(m_plots.size()));

  //Resize Matrices
  {
    const std::vector<QTableWidget *> v = CollectMatrices();
    const std::size_t sz = v.size();
    for (std::size_t i = 0; i!=sz; ++i)
    {
      QTableWidget * const table = v[i];
      table->setColumnCount(n);
      table->setRowCount(n);
    }
  }
  //Vectors
  {
    const std::vector<QTableWidget *> v = CollectVectors();
    const std::size_t sz = v.size();
    for (std::size_t i = 0; i!=sz; ++i)
    {
      QTableWidget * const table = v[i];
      table->setRowCount(n);
    }
  }

  //Add '?' to ui->table_states' possible empty cells
  for (int i=0; i!=n; ++i)
  {
    if (!ui->table_states->item(i,0))
    {
      QTableWidgetItem * const item = new QTableWidgetItem("?");
      ui->table_states->setItem(i,0,item);
    }
  }
  UpdateLegends();
}

void QtMainDialog::UpdateLegends()
{
  const std::vector<std::string> legend = GetLegend();
  const int n = boost::numeric_cast<int>(legend.size());
  for (int i=0; i!=n; ++i)
  {
    assert(i < boost::numeric_cast<int>(m_plots.size()));
    m_plots[i]->setTitle(legend[i].c_str());
    m_plots[i]->setAxisTitle(QwtPlot::yLeft,legend[i].c_str());
  }
  //Matrices
  {
    const std::vector<QTableWidget *> v = CollectMatrices();
    const std::size_t sz = v.size();
    for (std::size_t i = 0; i!=sz; ++i)
    {
      QTableWidget * const table = v[i];
      assert(table->columnCount() == boost::numeric_cast<int>(legend.size()));
      assert(table->rowCount() == boost::numeric_cast<int>(legend.size()));
      for (int j = 0; j!=n; ++j)
      {
        {
          QTableWidgetItem * const item = new QTableWidgetItem;
          item->setText(legend[j].c_str());
          table->setVerticalHeaderItem(j,item);
        }
        {
          QTableWidgetItem * const item = new QTableWidgetItem;
          item->setText(legend[j].c_str());
          table->setHorizontalHeaderItem(j,item);
        }
      }
      table->resizeColumnsToContents();
      table->resizeRowsToContents();
      table->update();
      table->setFixedHeight(
        table->verticalHeader()->length()   + 2 + table->horizontalHeader()->height());
      //table->setFixedSize(
      //  table->horizontalHeader()->length() + 2 + table->verticalHeader()->width(),
      //  table->verticalHeader()->length()   + 2 + table->horizontalHeader()->height());
    }
  }
  //Vectors
  {
    const std::vector<QTableWidget *> v = CollectVectors();
    const std::size_t sz = v.size();
    for (std::size_t i = 0; i!=sz; ++i)
    {
      QTableWidget * const table = v[i];
      assert(table->rowCount() == boost::numeric_cast<int>(legend.size()));
      for (int j = 0; j!=n; ++j)
      {
        QTableWidgetItem * const item = new QTableWidgetItem;
        item->setText(legend[j].c_str());
        table->setVerticalHeaderItem(j,item);
      }
      table->resizeColumnsToContents();
      table->resizeRowsToContents();
      table->setFixedHeight(
        table->verticalHeader()->length()   + 2 + table->horizontalHeader()->height());
      //table->setFixedSize(
      //  table->horizontalHeader()->length() + 2 + table->verticalHeader()->width(),
      //  table->verticalHeader()->length()   + 2 + table->horizontalHeader()->height());
    }
  }
}



void QtMainDialog::on_button_start_clicked()
{
  DoSim();
}

 

 

 

 

 

zip.sh

 

#!/bin/sh

echo "Removing user information"
rm *.user

echo "Removing possible temp file"
rm copy.txt
rm tmp.txt


echo "Creating of all main folders"

mkdir temp_zip
mkdir temp_zip/Classes
mkdir temp_zip/Libraries
mkdir temp_zip/Test

echo "Creating of all subfolders"

mkdir temp_zip/Classes/CppKalmanFilter
mkdir temp_zip/Classes/CppMatrix
mkdir temp_zip/Classes/CppQtMatrix
mkdir temp_zip/Classes/CppTrace
mkdir temp_zip/Libraries/fparser4.4.3
mkdir temp_zip/Libraries/fparser4.4.3/extrasrc
mkdir temp_zip/Libraries/fparser4.5.1
mkdir temp_zip/Libraries/fparser4.5.1/extrasrc
mkdir temp_zip/Test/CppKalmanFilterExample12

echo "Copying files"

cp ../../Classes/CppKalmanFilter/kalmanfilter.cpp temp_zip/Classes/CppKalmanFilter/kalmanfilter.cpp
cp ../../Classes/CppKalmanFilter/kalmanfilter.h temp_zip/Classes/CppKalmanFilter/kalmanfilter.h
cp ../../Classes/CppKalmanFilter/whitenoisesystem.cpp temp_zip/Classes/CppKalmanFilter/whitenoisesystem.cpp
cp ../../Classes/CppKalmanFilter/whitenoisesystem.h temp_zip/Classes/CppKalmanFilter/whitenoisesystem.h
cp ../../Classes/CppMatrix/matrix.cpp temp_zip/Classes/CppMatrix/matrix.cpp
cp ../../Classes/CppMatrix/matrix.h temp_zip/Classes/CppMatrix/matrix.h
cp ../../Classes/CppQtMatrix/Licence.txt temp_zip/Classes/CppQtMatrix/Licence.txt
cp ../../Classes/CppQtMatrix/qtmatrix.cpp temp_zip/Classes/CppQtMatrix/qtmatrix.cpp
cp ../../Classes/CppQtMatrix/qtmatrix.h temp_zip/Classes/CppQtMatrix/qtmatrix.h
cp ../../Classes/CppTrace/trace.h temp_zip/Classes/CppTrace/trace.h
cp ../../Libraries/fparser4.4.3/extrasrc/fp_identifier_parser.inc temp_zip/Libraries/fparser4.4.3/extrasrc/fp_identifier_parser.inc
cp ../../Libraries/fparser4.4.3/extrasrc/fp_opcode_add.inc temp_zip/Libraries/fparser4.4.3/extrasrc/fp_opcode_add.inc
cp ../../Libraries/fparser4.4.3/extrasrc/fpaux.hh temp_zip/Libraries/fparser4.4.3/extrasrc/fpaux.hh
cp ../../Libraries/fparser4.4.3/extrasrc/fptypes.hh temp_zip/Libraries/fparser4.4.3/extrasrc/fptypes.hh
cp ../../Libraries/fparser4.4.3/fparser.cc temp_zip/Libraries/fparser4.4.3/fparser.cc
cp ../../Libraries/fparser4.4.3/fparser.hh temp_zip/Libraries/fparser4.4.3/fparser.hh
cp ../../Libraries/fparser4.4.3/fpconfig.hh temp_zip/Libraries/fparser4.4.3/fpconfig.hh
cp ../../Libraries/fparser4.5.1/extrasrc/fp_identifier_parser.inc temp_zip/Libraries/fparser4.5.1/extrasrc/fp_identifier_parser.inc
cp ../../Libraries/fparser4.5.1/extrasrc/fp_opcode_add.inc temp_zip/Libraries/fparser4.5.1/extrasrc/fp_opcode_add.inc
cp ../../Libraries/fparser4.5.1/extrasrc/fpaux.hh temp_zip/Libraries/fparser4.5.1/extrasrc/fpaux.hh
cp ../../Libraries/fparser4.5.1/extrasrc/fptypes.hh temp_zip/Libraries/fparser4.5.1/extrasrc/fptypes.hh
cp ../../Libraries/fparser4.5.1/fparser.cc temp_zip/Libraries/fparser4.5.1/fparser.cc
cp ../../Libraries/fparser4.5.1/fparser.hh temp_zip/Libraries/fparser4.5.1/fparser.hh
cp ../../Libraries/fparser4.5.1/fpconfig.hh temp_zip/Libraries/fparser4.5.1/fpconfig.hh
cp ../../Test/CppKalmanFilterExample12/CppKalmanFilterExample12Desktop.pro temp_zip/Test/CppKalmanFilterExample12/CppKalmanFilterExample12Desktop.pro
cp ../../Test/CppKalmanFilterExample12/CppKalmanFilterExample12Source.zip temp_zip/Test/CppKalmanFilterExample12/CppKalmanFilterExample12Source.zip
cp ../../Test/CppKalmanFilterExample12/Licence.txt temp_zip/Test/CppKalmanFilterExample12/Licence.txt
cp ../../Test/CppKalmanFilterExample12/main.cpp temp_zip/Test/CppKalmanFilterExample12/main.cpp
cp ../../Test/CppKalmanFilterExample12/maindialog.cpp temp_zip/Test/CppKalmanFilterExample12/maindialog.cpp
cp ../../Test/CppKalmanFilterExample12/maindialog.h temp_zip/Test/CppKalmanFilterExample12/maindialog.h
cp ../../Test/CppKalmanFilterExample12/qtkalmanfilteralgorithmdialog.cpp temp_zip/Test/CppKalmanFilterExample12/qtkalmanfilteralgorithmdialog.cpp
cp ../../Test/CppKalmanFilterExample12/qtkalmanfilteralgorithmdialog.h temp_zip/Test/CppKalmanFilterExample12/qtkalmanfilteralgorithmdialog.h
cp ../../Test/CppKalmanFilterExample12/qtkalmanfilteralgorithmdialog.ui temp_zip/Test/CppKalmanFilterExample12/qtkalmanfilteralgorithmdialog.ui
cp ../../Test/CppKalmanFilterExample12/qtmain.cpp temp_zip/Test/CppKalmanFilterExample12/qtmain.cpp
cp ../../Test/CppKalmanFilterExample12/qtmaindialog.cpp temp_zip/Test/CppKalmanFilterExample12/qtmaindialog.cpp
cp ../../Test/CppKalmanFilterExample12/qtmaindialog.h temp_zip/Test/CppKalmanFilterExample12/qtmaindialog.h
cp ../../Test/CppKalmanFilterExample12/qtmaindialog.ui temp_zip/Test/CppKalmanFilterExample12/qtmaindialog.ui
cp ../../Test/CppKalmanFilterExample12/zip.sh temp_zip/Test/CppKalmanFilterExample12/zip.sh

FILENAME="CppKalmanFilterExample12Source"
ZIP_FILENAME=$FILENAME".zip"

echo "Compressing files"

cd temp_zip
zip -r $FILENAME Classes
zip -r $FILENAME Libraries
zip -r $FILENAME Test
cd ..
cp "temp_zip/"$ZIP_FILENAME $ZIP_FILENAME

echo "Cleaning up"

echo "Emptying subfolders"

rm temp_zip/Classes/CppKalmanFilter/*.*
rm temp_zip/Classes/CppMatrix/*.*
rm temp_zip/Classes/CppQtMatrix/*.*
rm temp_zip/Classes/CppTrace/*.*
rm temp_zip/Libraries/fparser4.4.3/*.*
rm temp_zip/Libraries/fparser4.4.3/extrasrc/*.*
rm temp_zip/Libraries/fparser4.5.1/*.*
rm temp_zip/Libraries/fparser4.5.1/extrasrc/*.*
rm temp_zip/Test/CppKalmanFilterExample12/*.*

echo "Removing subfolders"

rmdir temp_zip/Classes/CppKalmanFilter
rmdir temp_zip/Classes/CppMatrix
rmdir temp_zip/Classes/CppQtMatrix
rmdir temp_zip/Classes/CppTrace
rmdir temp_zip/Libraries/fparser4.4.3/extrasrc
rmdir temp_zip/Libraries/fparser4.4.3
rmdir temp_zip/Libraries/fparser4.5.1/extrasrc
rmdir temp_zip/Libraries/fparser4.5.1
rmdir temp_zip/Test/CppKalmanFilterExample12

echo "Removing main folders"

rmdir temp_zip/Classes
rmdir temp_zip/Libraries
rmdir temp_zip/Test

echo "Removing temporary folder"

rm temp_zip/*.*
rmdir temp_zip

echo "Done"

# CreateQtProjectZipFile, version 1.3
# Copyright (C) 2012 Richel Bilderbeek
# Programmed on the 10th of June 2012
# by Richel Bilderbeek
#
# CreateQtProjectZipFile can be downloaded from http://www.richelbilderbeek.nl/ToolCreateQtProjectZipFile.htm
# Licenced under GPL 3.0

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml