/*!
  \file
  \brief TR 2525 file for testing Toy Problem of mpf for Covariance Estimation
  \author Vaclav Smidl.

  -----------------------------------
  BDM++ - C++ library for Bayesian Decision Making under Uncertainty

  Using IT++ for numerical operations
  -----------------------------------
*/



#include <estim/particles.h>
#include <estim/ekf_template.h>
#include <stat/functions.h>


#include "../pmsm.h"
#include "simulator.h"
#include "../sim_profiles.h"
#include "user_info.h"
#include "stat/loggers.h"

using namespace bdm;

int main ( int argc, char* argv[] ) {
	const char *fname;
	if ( argc>1 ) {fname = argv[1];	}
	else { fname = "unitsteps.cfg"; }
	UIFile F ( fname );

	double h = 1e-6;
	int Nsimstep = 125;


	// Kalman filter
	int Ndat;
	int Npart;
	F.lookupValue ( "ndat", Ndat );
	F.lookupValue ( "Npart",Npart );
	mpdf* evolQ = UI::build<mpdf>( F, "Qrw" );
	vec Qdiag;
	vec Rdiag;
	UI::get( Qdiag, F, "dQ" ); //( "1e-6 1e-6 0.001 0.0001" ); //zdenek: 0.01 0.01 0.0001 0.0001
	UI::get( Rdiag, F, "dR" );// ( "1e-8 1e-8" ); //var(diff(xth)) = "0.034 0.034"

	// internal model

IMpmsm fxu;
//                  Rs    Ls        dt       Fmag(Ypm)    kp   p    J     Bf(Mz)
fxu.set_parameters ( 0.28, 0.003465, Nsimstep*h, 0.1989, 1.5 ,4.0, 0.04, 0.0 );
	// observation model
	OMpmsm hxu;

	vec mu0= "0.0 0.0 0.0 0.0";
	chmat Q ( Qdiag );
	chmat R ( Rdiag );
	EKFCh KFE ;
	KFE.set_parameters ( &fxu,&hxu,Q,R );
	KFE.set_est ( mu0, chmat ( zeros ( 4 ) ) );
	KFE.set_rv ( rx );

	RV rQ ( "{Q }","4" );
	EKFCh_dQ KFEp ;
	KFEp.set_parameters ( &fxu,&hxu,Q,R );
	KFEp.set_est ( mu0, chmat ( zeros ( 4 ) ) );

	MPF<EKFCh_dQ> M;
	M.set_parameters ( evolQ,evolQ,Npart );
	// initialize
	evolQ->condition ( 10*Qdiag ); //Zdenek default
	M.set_statistics ( evolQ->_e() , &KFEp );
	//

	M.set_rv ( concat ( rQ,rx ) );

	dirfilelog *L = UI::build<dirfilelog>( F, "logger" );// ( "exp/mpf_test",100 );
	int l_X = L->add ( rx, "xt" );
	int l_D = L->add ( concat ( ry,ru ), "" );
	int l_Q= L->add ( rQ, "" );

	KFE.set_options ( "logbounds" );
	KFE.log_add ( *L,"KF" );
	M.set_options ( "logbounds" );
	M.log_add ( *L,"M" );
	L->init();

	// SET SIMULATOR
	pmsmsim_set_parameters ( 0.28,0.003465,0.1989,0.0,4,1.5,0.04, 200., 3e-6, h );
	vec dt ( 2 );
	vec ut ( 2 );
	vec xt ( 4 );
	vec xtm=zeros ( 4 );
	double Ww=0.0;
	vec vecW;
	UI::get( vecW, F, "profile" );

	for ( int tK=1;tK<Ndat;tK++ ) {
		//Number of steps of a simulator for one step of Kalman
		for ( int ii=0; ii<Nsimstep;ii++ ) {
			//simulator
			sim_profile_vec01t ( Ww,vecW );
			pmsmsim_step ( Ww );
		};
		ut ( 0 ) = KalmanObs[4];
		ut ( 1 ) = KalmanObs[5];
		xt = fxu.eval ( xtm,ut ) + diag ( sqrt ( Qdiag ) ) *randn ( 4 );
		dt = hxu.eval ( xt,ut );
		xtm = xt;

		//Variances
		if ( tK==1000 )  Qdiag ( 0 ) *=10;
		if ( tK==2000 ) Qdiag ( 0 ) /=10;
		if ( tK==3000 )  Qdiag ( 1 ) *=10;
		if ( tK==4000 ) Qdiag ( 1 ) /=10;
		if ( tK==5000 )  Qdiag ( 2 ) *=10;
		if ( tK==6000 ) Qdiag ( 2 ) /=10;
		if ( tK==7000 )  Qdiag ( 3 ) *=10;
		if ( tK==8000 ) Qdiag ( 3 ) /=10;

		//estimator
		KFE.bayes ( concat ( dt,ut ) );
		M.bayes ( concat ( dt,ut ) );

		L->logit ( l_X,xt );
		L->logit ( l_D,concat ( dt,ut ) );
		L->logit ( l_Q,Qdiag );

		KFE.logit ( *L );
		M.logit ( *L );
		L->step();
	}
	L->finalize();
	//Exit program:

	delete L;
	return 0;
}

