// Last Update: 28-12-22
// Change IDE Font: Tools=>Options=>Source=>Font
// Code to be used for full sensor calibration!!!!!
// The code is developed with: PELLES C for Windows, Version 9.00.9 as Win64 Console Program
// For accuracy reasons the code should be compiled, and excecuted in 64 bit.
// Pelles-ST-Rotated-Ellipsoid-Fitting-for-Sensor-Calibration
// MAGNETOMETER CALIBRATION using 216 measurements.
// GAUSS-JORDAN (GJ) is used for matrix inversion
// 1: Calculation of Calibration Shift Vector Vx, Vy, Vz.
// 2: Calculation of the symmetric ellipsoid fit-matrix that will deliver the eigenvalues and eigenvectors.
// Eigenvalues calculated with Jakobi Eigenvalue Code
// Improved Eigenvector calculation using Gauss-elimination method.
// Ref.2: ST Design Tip DT0059. Ellipsoid or sphere fitting for sensor calibration by Andrea Vitali.
// Ref.3: Freescale Semiconductor Application Note. Document Number: AN4246 Rev. 4.0, 11/2015
// Calibrating an eCompass in the Presence of Hard-and Soft-Iron Interference by Talat Ozyagcilar.
//........................................................................................
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//--( Start Main )--( Start Main )--( Start Main )--( Start Main )--( Start Main )----
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h> //to define uint64_t
#define Type double //Note: The analysis will be performed in doubles
#define _R 216 // Number of Rows of the input data matrix
#define _C 9 // Number of Columns
#define M _C
#define N _C
#define _L 3
#define _n 3 // Enter the size of the square symmetric matrix
#define _row _n
#define _col _n
#define _m _n
#define _Gcol _m // Number of Colums for the Augmented Matrix of the Gauss elimination
int i, j, k, l, p, q, flag;
int z =_col;
int n= _row;
int R=_R;
int C1 =_C;
int L=_L;
// Def: matrix m x p (m=rows ,p=columns)
Type A[_row][_col], UpsA[_row][_col], d[_row][_col], s[_row][_col], s1[_row][_col], s1t[_row][_col];
Type aG[_row][_Gcol], x[_row]; //This matrix is used for Gauss elimination to calculate the eigenvectors.
Type C[_row][_col] , CTp[_col][_row]; // Matrix and transposed matrix of eigenvectors
Type sltt[_row][_col]; //This matrix is used to test the juctaposition of the eigenvectors.
//Type sT[_row][_col]; //This matrix is the transposed eigenvector matrix sT used to test the transformation
Type temp[_row][_col];
Type hmax, theta, ratio;
Type pi=3.141592654;
Type zero=0.00001; //0.00001 zero determines the accurcacy of the calculation
Type radius; // Vector length
Type DFileIn[_R][_L];
Type DCalib1[_R][_L];
Type DCalib2[_R][_L];
Type D[_R][_C]; //D = input matrix m x p (m=rows=24,p=columns=4)
//m rows is aantal metingen, bv 24 bij kubus onder 90 graden
//D[m][0] = bv gemeten X-waarde in mGauss
//D[m][1] = bv gemeten Y-waarde in mGauss
//D[m][2] = bv gemeten Z-waarde in mGauss
Type ReduD[_R][_C];
Type DT [_C][_R], ReduDT [_C][_R]; // DT= transposed input matrix p x m (p=rows=4,m=columns)
Type DTD[_C][_C], ReduDTD[_C][_C];
Type OrigDTD[_C][_C]; // auxiliary matrix used for checking matrix-inversion
Type DTDh[_C][_C];
Type Dh1[_C][_C]; // auxiliary matrix Dh1=(DTp x D)=>p x p=>9 x 9 matrix
Type NVec[_R]; // N-vector filled with 24x1
Type DTNVec[_C]; // Hulp Vector DTNVec[9x1]=DT.NVec
Type Vec[_C]; // "Solution" vector
Type Vghi[3]; // part of "Solution" vector
Type VS[3]; // Shift vector
Type VS1[3]; // Rotated Shift vector
Type VS2[3];
Type A3[3][3]; //matrix to calculate the shift vector
Type HA3[3][3]; //Auxiliary matrix
Type HHA3[3][3]; //Auxiliary matrix to check A3 Matrixinversion
Type B3[3][3]; //hulp matrix
Type A4[4][4]; //hulp matrix
Type B4[4][4]; //hulp matrix
Type HATemp[4][4]; //hulp matrix
Type T[4][4];
Type TT[4][4];
Type EiVec[3][3], EiVecTp[3][3];
Type hEiVec[3][3], hEiVecTp[3][3];
Type NormEiVec[3][3], NormEiVecTp[3][3];
Type JacoEiVals[3][3], TstJacoEiVals[3][3];
Type JacoEiVec[3][3], JacoEiVecTp[3][3];
Type DetVal;
Type Wmin1[3][3]; //Calibration matrix W**-1
void importInteger3ColDataTextFile(Type* A);
void exportRawMagdata2textfile(Type* A);
void exportCalibMagdata2textfile(Type* A);
//void exportFinalCalibResults2textfile(Type* A);
void exportFinalCalibResults2textfile(void);
void MatrixMathPrint(Type* A , int row , int col, int decimals, char *Stringlabel);
void MatrixMathSciePrint(Type* A, int row, int col, int decimals, char *Stringlabel);
void MatrixMultiplyConstant(Type* A, Type* B, int row, int col, Type constant);
void MatrixMathCopy(Type* A , int row , int col, Type* B);
void MatrixMathMultiply(Type* A, Type* B, int m, int p, int n, Type* C);
void MatrixMathMatrixVectorMultiply(Type* A, Type* U, int m, int p, Type* V);
void MatrixMathTranspose(Type* A, int row, int col, Type* C);
void MatrixMath_I_Matrix(Type* A, int row, int col);
int MatrixMathInvert(Type* A, int n);
void MatrixMathAddition (Type* A, Type* B, int row, int col, Type* C);
void MatrixMathSubtract (Type* A, Type* B, int row, int col, Type* C);
void GaussElimination(Type* A, int row, int col);
Type MatrixMathDeterminant(Type* _D, int _t);
Type determinant(Type _a[_row][_col], int _t);
void main()
{
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Calcul-Step 1: Importing the 216 x,y,z magnetometer measurements.
// FILENAAM is "d:\\Pelles C-SourceCode\\sensordata\\recorded-sensordata.txt";
importInteger3ColDataTextFile((Type*)DFileIn);
printf("The from file imported Data Matrix is: \n");
for (i=0;i < R;i++)
{
for (j=0;j < L;j++)
{
D[i][j] = DFileIn[i][j];
printf(" %.0f", D[i][j]);
printf("\t");
}
printf("\n");
}
// For quality control the raw measurements are exportd as GnuPlot compatible file.
exportRawMagdata2textfile((Type*) DFileIn);
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//================= All 216 Magnetic Data Records have been loaded ======================
// Calcul-Step 2: Calculating the tilted ellipsoid as discussed in[Ref.2] =====
// This factor has experimentally been figured out to down-scale the poorly conditioned
// matrix for successfull inversion.
Type factor = 0.001;
Type factor1;
for (i=0; i < _R ; i++)
{
D[i][3] = 2*D[i][0]*D[i][1]; // 2XY
D[i][4] = 2*D[i][0]*D[i][2]; // 2XZ
D[i][5] = 2*D[i][1]*D[i][2]; // 2YZ
D[i][6] = 2*D[i][0]; // 2X
D[i][7] = 2*D[i][1]; // 2Y
D[i][8] = 2*D[i][2]; // 2Z
D[i][0] = D[i][0]*D[i][0]; // XX
D[i][1] = D[i][1]*D[i][1]; // YY
D[i][2] = D[i][2]*D[i][2]; // ZZ
}
// MatrixMathPrint((Type*)D,_R,_C,1,"It is assumed that all Bit-value measurements lay on a Rotated Ellipsoid.");
MatrixMathTranspose((Type*)D,_R,_C,(Type*)DT); //calculate the transposed matrix DT
// MatrixMathPrint((Type*)DT,_C,_R,1,"DT is the transposed D matrix");
// Auxilliary matrix OrigDTD stores the original product matrix DTD, later to be used for matrix inversion check.
MatrixMathMultiply((Type*)DT, (Type*)D, C1,R,C1, (Type*)OrigDTD);
// Fill NVec[216x1] vector with ones.
for (i=0; i < _R ; i++) NVec[i] = 1.0;
// _R=216 _C=9
MatrixMathMatrixVectorMultiply((Type*)DT,(Type*)NVec,_C,_R,(Type*)DTNVec);
// vector DTNVec[9x1] = DT[9x216].NVec[216x1]
// START matrix inversion. Prepare inversion by down-scaling matrix D and DT with factor.
// Because of poor matrix condition down-scaling the matrices is required for succesfull inversion.
// -------------------------------------------------------------------------------------
MatrixMultiplyConstant((Type*)D , (Type*)ReduD ,R,C1, factor); //Reduce Matrix D with factor
MatrixMultiplyConstant((Type*)DT, (Type*)ReduDT ,C1,R, factor); //Reduce Matrix DT with factor
MatrixMathMultiply((Type*)ReduDT, (Type*) ReduD, C1,R,C1, (Type*) ReduDTD); //DTD is here reduced
// Gauss-Jordan Matrix Inversion.
// ---------------------------------------
MatrixMathInvert((Type*)ReduDTD,C1); //calculate inverse of down-scaled matrix DTD and store in DTD
// ----------------------------------------
// Up-Scaling the inverted down-scaled matrix
factor1=factor*factor;
MatrixMultiplyConstant((Type*)ReduDTD, (Type*)DTD, C1,C1, factor1);
// DTD = INV(DT.D)[[9x9] matrix of the oroginal (DT.D)[[9x9] matrix.
MatrixMathSciePrint((Type*)DTD,C1,C1,8 ,"The up-scaled inverted Matrix in scientific notation.");
// Check the matrix inversion.
MatrixMathMultiply((Type*)DTD, (Type*)OrigDTD, C1,C1,C1, (Type*) Dh1);
MatrixMathPrint((Type*)Dh1,_C,_C,6,"The Matrixinversion is Checked. If unity matrix then OK.");
// Inverted DTD[9x9] matrix is Up-scaled with factor1, and the inversion has been checked.
// END of Gauss-Jordan matrix inversion.
// ---------------------------------------------------------------------------------------
// Calculate the Least-Square solution vector Vec[1x9]=Vec[a,b,c,d,e,f,g,h,i]
printf("\n");
for (i=0; i < C1; i++) printf("DTNVec= %.0f\n", DTNVec[i]); // DTNVec[9x1]
printf("\n");
// Calculation of LS solution vector Vec[9x1]
MatrixMathMatrixVectorMultiply((Type*)DTD,(Type*)DTNVec,_C,_C,(Type*)Vec);
for (i=0; i < C1; i++)
{
printf("The LS solution vector Vec= %6.4e\n", Vec[i]);
}
// a XX+ b YY+ c ZZ+ d 2XY+ e 2XZ+ f 2YZ+ g 2X+ h 2Y+ i 2Z =1
// Vec[0]XX+Vec[1]YY+Vec[2]ZZ+Vec[3]2XY+Vec[4]2XZ+Vec[5]2YZ+Vec[6]2X+Vec[7]2Y+Vec[8]2Z =1
//== With the LS-calculation the optimum ellipsoid, being the locus of the raw magnetometer measurements, is found. ==
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Calcul-Step 3: Calculating the offset vector of the ellipsoid as per [Ref.2]
// The PARTIAL derivatives dF/dX=0, dF/dY=0, dF/dZ=0 from the second degree function
// F(X,Y,Z)=Vec[0]XX+Vec[1]YY+Vec[2]ZZ+Vec[3]2XY+Vec[4]2XZ+Vec[5]2YZ+Vec[6]2X+Vec[7]2Y+Vec[8]2Z-1
// result in 3 equations from which the center i.e. offset of the ellipsoid is calculated.
// The formalism of [Ref.2] is equivalent and calculates the offset with auxiliary matrix A3[3][3]
// and vector Vghi[3].
A3[0][0]=Vec[0]; //a
A3[0][1]=Vec[3]; //d
A3[0][2]=Vec[4]; //e
A3[1][0]=Vec[3]; //d
A3[1][1]=Vec[1]; //b
A3[1][2]=Vec[5]; //f
A3[2][0]=Vec[4]; //e
A3[2][1]=Vec[5]; //f
A3[2][2]=Vec[2]; //c
MatrixMathCopy((Type*) A3, 3,3, (Type*) HA3); //Store A3 in auxiliary matrix HA3 for inversion check
MatrixMathInvert((Type*) A3,3); //calculate inverse van A3[3x3] matrix
// Check the inversion of matrix A3
MatrixMathMultiply((Type*) A3, (Type*) HA3, 3,3,3, (Type*) HHA3);
MatrixMathPrint((Type*)HHA3,3,3,6,"HHA3[3x3] stores the Matrixinversion Check. If HHA3 is unity matrix then OK.");
MatrixMultiplyConstant((Type*) A3, (Type*) A3, 3, 3, -1); // multiply matrix A3 with -1
Vghi[0]=Vec[6]; //g
Vghi[1]=Vec[7]; //h
Vghi[2]=Vec[8]; //i
// Calculation Offset vector VS[3]
printf("\n");
MatrixMathMatrixVectorMultiply((Type*) A3,(Type*)Vghi,3,3,(Type*)VS);
printf("Offset vector X component VSx= %.0f\n",VS[0]);
printf("Offset vector Y component VSy= %.0f\n",VS[1]);
printf("Offset vector Z component VSz= %.0f\n",VS[2]);
printf("\n");
printf("\n");
//========= The offset vector of the rotated ellipsoid is determined ===========
//------ Calculating the matrix that represents the rotated ellipsoid, translated
// with the offset vector to the origin. Calculation as per [Ref.2] ------
A4[0][0]=Vec[0]; //a
A4[0][1]=Vec[3]; //d
A4[0][2]=Vec[4]; //e
A4[0][3]=Vec[6]; //g
A4[1][0]=Vec[3]; //d
A4[1][1]=Vec[1]; //b
A4[1][2]=Vec[5]; //f
A4[1][3]=Vec[7]; //h
A4[2][0]=Vec[4]; //e
A4[2][1]=Vec[5]; //f
A4[2][2]=Vec[2]; //c
A4[2][3]=Vec[8]; //i
A4[3][0]=Vec[6]; //g
A4[3][1]=Vec[7]; //h
A4[3][2]=Vec[8]; //i
A4[3][3]=-1;
T[0][0]=T[1][1]=T[2][2]=T[3][3]=1;
T[0][1]=T[0][2]=T[0][3]=T[1][0]=T[1][2]=T[1][3]=T[2][0]=T[2][1]=T[2][3]=0;
T[3][0]=VS[0];
T[3][1]=VS[1];
T[3][2]=VS[2];
// Above constructed matrix T{4x4} reads:
// {1,0,0,0},
// {0,1,0,0},
// {0,0,1,0},
// {VS[0],VS[1],VS[2],1}};
// Calculate the transposed matrix TT[4x4] of matrix T[4x4]
MatrixMathTranspose((Type*)T,4,4,(Type*)TT);
MatrixMathMultiply((Type*) A4, (Type*)TT, 4,4,4, (Type*) HATemp);
MatrixMathMultiply((Type*)T, (Type*)HATemp, 4,4,4, (Type*) B4);
MatrixMathSciePrint((Type*)B4,4,4,8 ,"B4[4x4] stores T[4x4].A[4x4].TT[4x4].");
// Calculate the value of the ellipsoid function F(X,Y,Z) for the offset values X0, Y0, Z0
Type FX0Y0Z0= Vec[0]*VS[0]*VS[0] +Vec[1]*VS[1]*VS[1] +Vec[2]*VS[2]*VS[2] +
2*Vec[3]*VS[0]*VS[1] +2*Vec[4]*VS[0]*VS[2] +2*Vec[5]*VS[1]*VS[2] +
2*Vec[6]*VS[0] +2*Vec[7]*VS[1] +2*Vec[8]*VS[2] -1;
printf("\n");
// Note: B4[3][3]= g*X0+h*Y0+i*Z0-1 = Vec[6]*VS[0] +Vec[7]*VS[1] +Vec[8]*VS[2] -1;
// Voor afleiding van B4[3][3]=F(X0,Y0,Z0) zie mijn notes.
printf("Note: The value of B4[3][3] is equal to F(X0,Y0,Z0)= %.5f\n",FX0Y0Z0);
printf("\n");
// Extract the 3x3 matrix B3 from the 4x4 matrix B4
for (i=0; i < 3; i++)
{
for (j=0;j < 3;j++)
{
B3[i][j] = B4[i][j];
}
}
// MatrixMathSciePrint((Type*) B3,3,3,8 ,"B3[3x3].");
double val;
val = -1/ B4[3][3];
// printf("The value of val= %.5f\n",val);
MatrixMultiplyConstant((Type*) B3, (Type*) B3, 3, 3, val);
printf("\n");
MatrixMathSciePrint((Type*) B3,3,3,8 ,"B3[3x3] the fit-matrix of the (tilted) shifted ellipsoid is:");
printf("\n\n");
printf("Calculation of the Offset-Vector and fit-matrix of rotated Ellipsoid translated to
the origin has been completed.\n");
printf("\n");
// ---- Calculation of the (ellipsoid) Offset-Vector, and the rotated, translated ellipsoid fit-matrix
// as per [Ref.2] is completed --------------------------
printf("********************************************************************************************");
printf("\n");
printf("********************************************************************************************");
printf("\n");
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Calcul-STEP 4: Eigenvalue calculation of fit-matrix A[3x3].
MatrixMathCopy((Type*) B3,3,3, (Type*)A); //For convenience matrix B3 is renamed to A
// MatrixMathSciePrint((Type*)A,z,z,12,"The symmetric fit-matrix A to calculate eigen values
and vectors in scientific notation is: ");
// Calculate the determinant of fit-matrix A[3x3] for later check of eigenvalue product.
// DetVal=MatrixMathDeterminant((Type *) A, z);
DetVal=MatrixMathDeterminant((Type *) A, n);
printf("Determinant of Matrix A = ");
printf("%6.6e", DetVal);
printf("\n");
// To improve the Jakobi eigenvalue calculation the ellipsoid A[3][3] will be upscaled with upscalefactor .
Type upscalefactor = 10e+08;
Type downscalefactor; // is 1/upscalefactor
MatrixMultiplyConstant((Type*)A, (Type*)UpsA,z,z,upscalefactor);
MatrixMathSciePrint((Type*)UpsA,z,z,6,"The symmetric upscaled matrix UpsA[3][3] in scientific notation is: ");
// **********************************************************************************************
// **********************************************************************************************
// ******************** Jakobi Eigenvalue and Eigenvector Code Ref.5 ****************************
// **********************************************************************************************
// **********************************************************************************************
// Jakobi Step 1: Read the symmetric Matrix UpsA
// Jakobi Step 2: Initialize d=UpsA and S=I
MatrixMathCopy((Type*)UpsA, z, z, (Type*)d); //Initialize matrix d = matrix UpsA
MatrixMath_I_Matrix((Type*)s, z, z); //Initialize s as I-Matrix
// Check print matrix d
// MatrixMathPrint((Type*)d, z, z, 12, "The copy matrix of matrix A=d[3x3] is: ");
float flag=1;
while(flag>zero)
{
// Jakobi Step 3: Find the largest off-diagonal element in d=|d[ij]| and let it be d[ij]
i=1;
j=2;
hmax = fabs(d[i][j]);
for (p = 0; p < z ; p ++)
{
for (q = 0; q < z ; q ++)
{
if (p!=q)
if (hmax < fabs(d[p][q]))
{
hmax=fabs(d[p][q]);
i=p; //index i, used below, is determined here
j=q; //index j, used below, is determined here
}
}
}
// printf("\n");
printf("Max off-line element of matrix d=> d[ij]= %.12f\n", d[i][j]);
// printf("\n");
// Jakobi Step 4: Find the rotational angle Theta
if (d[i][i]==d[j][j])
{
if (d[i][j] > 0)
{
theta=pi/4;
}
else
{
theta=-pi/4;
}
}
else
{
theta=0.5*atan(2*d[i][j]/(d[i][i]-d[j][j]));
}
printf("\n");
printf("The rotational angle Theta= %.4f\n", theta);
// Serial.print(theta,6);
printf("\n");
// Jakobi Step 5: Computate the matrix s1=s[p][q]
// Note: s1t is the transposed of s1
MatrixMath_I_Matrix((Type*)s1, z, z); //Initialize S1 as I-Matrix
MatrixMath_I_Matrix((Type*)s1t, z, z); //Initialize S1T as I-Matrix
s1[i][i]= cos(theta);
s1[j][j]= s1[i][i];
s1[j][i]= sin(theta);
s1[i][j]=-s1[j][i];
s1t[i][i]=s1[i][i];
s1t[j][j]=s1[j][j];
s1t[i][j]=s1[j][i];
s1t[j][i]=s1[i][j];
MatrixMathPrint((Type*)s1 , z, z, 3, "The matrix s1 is: ");
MatrixMathPrint((Type*)s1t, z, z, 3, "The matrix s1t is: ");
// Jakobi Step 6: Calculate D= S1TxDxS1 and S=SxS1
MatrixMathMultiply((Type*)s1t, (Type*)d, z, z, z, (Type*)temp);
MatrixMathMultiply((Type*)temp, (Type*)s1, z, z, z, (Type*)d);
MatrixMathSciePrint((Type*)d, z, z,6, "The Jakobi eigenvalue matrix of the upscaled matrix UpsA is: ");
MatrixMathMultiply((Type*)s,(Type*)s1, z, z, z, (Type*)temp);
MatrixMathCopy((Type*)temp, z, z, (Type*)s);
MatrixMathSciePrint((Type*)s, z, z, 6,"The Jakobi eigenvector matrix of the upscaled matrix UpsA is: ");
flag=0;
for (i = 0; i < z ; i ++) //check the sum of non-diagonal terms
for (j = 0; j < z ; j ++)
{
if(i!=j)
{
if(fabs(d[i][j]) > zero ) // zero=0.0001;
{
flag=flag+fabs(d[i][j]);
}
}
}
printf("\n");
printf("Flag= %.6f\n", flag);
printf("\n\n");
}
// ****************** END of Jakobi Eigenvalue While Loop ******************
// ***************** Check Calculation of Jakobi Eigenvalues ***************
// DOWNSCALING the Jakobi eigenvalues with:
downscalefactor=1/upscalefactor;
//check effect of changing order of eigenvalues
Type a=d[0][0];
Type b=d[1][1];
Type c=d[2][2];
d[0][0]=c; //a,b,c b,c,a c,a,b
d[1][1]=a;
d[2][2]=b;
printf("Finally the Jakobi Eigenvalues are: ");
for (i = 0; i < n ; i ++)
{
JacoEiVals[i][i]=d[i][i]*downscalefactor;
printf("%.6e ", JacoEiVals[i][i]);
}
printf("\n\n");
// Check if the product of the Jakobi eigenvalues equal is to determinant
// of the matrix A. All downscaled.
float eivalproduct =1;
for (i = 0; i < n ; i ++)
{
eivalproduct *= JacoEiVals[i][i];
}
printf(" The product of the 3 Eigenvalues is: %0.6e", eivalproduct);
printf("\n");
printf(" Determinant of Matrix A[3x3]= ");
printf("%6.6e", DetVal);
printf("\n\n");
printf("\nAAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA \n");
printf("End Eigenvalue Calculs - End Eigenvalue Calculs - End Eigenvalue Calculs - End Eigenvalue Calculs\n");
printf("AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA \n");
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Calcul-Step 5: Eigenvector calculation of fit-matrix A[3x3].
printf("\nBBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB \n");
printf("Start Gauss-Elim Eigenvector Calculs - Start Gauss-Elim Eigenvector Calculs \n");
printf("BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB \n");
// Start of loop over the eigenvalues of matrix A[3][3] to calculate the eigenvectors with Gauss-Elimination
for (l=0; l < n; l++)
{
MatrixMath_I_Matrix((Type*) temp,n,n); //was z
printf("\n");
printf(" The selected Jakobi eigenvalue to calculate its eigenvector is: %.6e\n", JacoEiVals[l][l]);
MatrixMultiplyConstant((Type*) temp,(Type*) temp,n,n,JacoEiVals[l][l]);
// Selected eigenvector for eigenvector calc.
MatrixMathSubtract((Type*) A,(Type*) temp,n,n,(Type*) aG);
// aG is the ellipsoid fit-matrix reduced by the selected eigenvalue
// MatrixMathSciePrint((Type*) aG,n,n,6,"The ellipsoid fit-matrix reduced by the selected eigenvalue is: ");
printf("\n");
GaussElimination((Type*) aG,n,n); // Gauss elimination produces the Eigenvector Matrix EiVec[3][3]
}
printf("\n");
MatrixMathSciePrint((Type*)EiVec,n,n,6,"The Gauss eliminated Eigenvector Matrix is: ");
printf("\n");
// Normalizing the Gauss eliminated eigenvectors EiVec
for (j = 0; j < z ; j ++){
for (i = 0; i < z ; i ++){
hEiVec[i][j]=EiVec[i][j];
}
}
Type Nhs1;
Nhs1= sqrt(hEiVec[0][0]*hEiVec[0][0] + hEiVec[1][0]*hEiVec[1][0] + hEiVec[2][0]*hEiVec[2][0]);
NormEiVec[0][0]=hEiVec[0][0]/Nhs1;
NormEiVec[1][0]=hEiVec[1][0]/Nhs1;
NormEiVec[2][0]=hEiVec[2][0]/Nhs1;
Nhs1= sqrt(NormEiVec[0][0]*NormEiVec[0][0] + NormEiVec[1][0]*NormEiVec[1][0] + NormEiVec[2][0]*NormEiVec[2][0]);
printf("Length check of normalized Gauss-EiVec1 eigenvector Nhs1= %.6e",Nhs1);
printf("\n");
Type Nhs2;
Nhs2= sqrt(hEiVec[0][1]*hEiVec[0][1] + hEiVec[1][1]*hEiVec[1][1] + hEiVec[2][1]*hEiVec[2][1]);
NormEiVec[0][1]=hEiVec[0][1]/Nhs2;
NormEiVec[1][1]=hEiVec[1][1]/Nhs2;
NormEiVec[2][1]=hEiVec[2][1]/Nhs2;
Nhs2= sqrt(NormEiVec[0][1]*NormEiVec[0][1] + NormEiVec[1][1]*NormEiVec[1][1] + NormEiVec[2][1]*NormEiVec[2][1]);
printf("Length check of normalized Gauss-EiVec2 eigenvector Nhs2= %.6e",Nhs2);
printf("\n");
Type Nhs3;
Nhs3= sqrt(hEiVec[0][2]*hEiVec[0][2] + hEiVec[1][2]*hEiVec[1][2] + hEiVec[2][2]*hEiVec[2][2]);
NormEiVec[0][2]=hEiVec[0][2]/Nhs3;
NormEiVec[1][2]=hEiVec[1][2]/Nhs3;
NormEiVec[2][2]=hEiVec[2][2]/Nhs3;
Nhs3= sqrt(NormEiVec[0][2]*NormEiVec[0][2] + NormEiVec[1][2]*NormEiVec[1][2] + NormEiVec[2][2]*NormEiVec[2][2]);
printf("Length check of normalized Gauss-EiVec3 eigenvector Nhs3= %.6e",Nhs3);
printf("\n\n");
MatrixMathTranspose((Type*) NormEiVec,n,n, (Type*) NormEiVecTp);
MatrixMathMultiply((Type*) NormEiVecTp, (Type*) NormEiVec,n,n,n, (Type*) temp);
MatrixMathSciePrint((Type*)temp,n,n,6,"Checking orthogonality of the Gauss Eigenvector Matrix: ");
printf("\n");
// ============================================================================
MatrixMathSciePrint((Type*)NormEiVec, n, n, 6, "The orthonormal matrix of Gauss eigenvectors is: ");
printf("\n");
MatrixMathMultiply((Type*) A, (Type*) NormEiVec,n,n,n, (Type*) temp);
MatrixMathMultiply((Type*) NormEiVecTp, (Type*) temp,n,n,n, (Type*) TstJacoEiVals);
MatrixMathSciePrint((Type*)TstJacoEiVals, n, n, 6, "Checking the Jacobi Eigenvalues by transforming
ellipsoid fit-matrix A with the orthonormal eigenvector matrices:");
printf("\n");
printf("The Jakobi Eigenvalues are: ");
for (i = 0; i < n ; i ++)
{
printf("%.6e ", JacoEiVals[i][i]);
}
printf("\n\n");
printf("\nBBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB \n");
printf("BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB BBBBBBBBBBB \n");
Type SQRTJacoEiVals[3][3]; //SQRT of Eigenvalue matrix JacoEiVals of fit-matrix A
// Type Wmin1[3][3]; //Calibration matrix W**-1
SQRTJacoEiVals[0][0]= sqrt(JacoEiVals[0][0]);
SQRTJacoEiVals[0][1]= 0.0;
SQRTJacoEiVals[0][2]= 0.0;
SQRTJacoEiVals[1][0]= 0.0;
SQRTJacoEiVals[1][1]= sqrt(JacoEiVals[1][1]);
SQRTJacoEiVals[1][2]= 0.0;
SQRTJacoEiVals[2][0]= 0.0;
SQRTJacoEiVals[2][1]= 0.0;
SQRTJacoEiVals[2][2]= sqrt(JacoEiVals[2][2]);
MatrixMathSciePrint((Type*)SQRTJacoEiVals, z, z, 6, "Square Root of the diagonal eigenvalue matrix JacoEiVals: ");
MatrixMathMultiply((Type*) NormEiVec, (Type*) SQRTJacoEiVals,n,n,n, (Type*) temp);
MatrixMathMultiply((Type*) temp, (Type*) NormEiVecTp,n,n,n, (Type*) Wmin1);
MatrixMathSciePrint((Type*)Wmin1, z, z, 6, "Calculation of W**-1=sqrt(A): ");
MatrixMathMultiply((Type*) Wmin1, (Type*) Wmin1,n,n,n, (Type*) temp);
MatrixMathSciePrint((Type*)temp, z, z, 6, "Check-Calculation of Wmin1xWmin1=A : ");
printf("\n");
// printf("1e Calibration Step: Shifting the raw ellipsoid data to origin coordinate system x',y',z'. \n");
for (i=0;i < R;i++) //R=216
{
for (j=0;j < L;j++) //L=3
{
// Apply the calculated shift to the 216 raw Bit-Value measurements.
DCalib1[i][j] = DFileIn[i][j]- VS[j];
}
}
int count=0;
while (count < R) //R=216
{
for (j=0;j < L;j++) //L=3
{
VS1[j] = DCalib1[count][j]; //Store the 3 values of each row in vector VS1
}
for (i=0;i < 3;i++)
{
VS2[i]=0;
for (j=0;j < 3;j++)
{
VS2[i]+= Wmin1[i][j]*VS1[j]; //multiply VS1 values with calibratie matrix
}
}
for (i=0;i < 3;i++)
{
DCalib2[count][i] = VS2[i];
}
count=count+1;
}
printf("\n The Calibrated measurements are: \n");
for (i=0;i < R;i++) //R=216 Rows
{
radius = sqrt(DCalib2[i][0]*DCalib2[i][0] + DCalib2[i][1]*DCalib2[i][1] + DCalib2[i][2]*DCalib2[i][2]);
for (j=0;j < L;j++) //L=3 Cols
{
printf(" %.3f", DCalib2[i][j]);
printf(" ");
}
printf(" %.3f", radius); //colmn 4
printf("\n");
}
printf("\n");
// For quality control, export the calibrated measurements as GnuPlot compatible file.
exportCalibMagdata2textfile((Type*) DCalib2);
printf("\n\n\nDisplay and export the Final Calibration Results: \n\n");
exportFinalCalibResults2textfile();
printf("\n");
i=10;
while (i < 100) //Endless loop to make sure .exe keeps results displaying on monitor
{
i++;
i--;
}
}
/*
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß-End Main-ßßßß
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
*/
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
//++++++++++++++++++++++ Start of function Library ++++++++++++++++++++++++++++++
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
//***************** IMPORT INTEGER Matrix via Text File Routine ******************
//Last update 16-2-2019
void importInteger3ColDataTextFile(Type* A)
{
// read all characters from a file, outputting only the letter 'b's
// it finds in the file
FILE *fp;
int i,j,k, val;
Type val1;
char* filename = "d:\\Pelles C-SourceCode\\sensordata\\recorded-sensordata.txt";
char c;
int C=3;
char dest[10];
i=0;
j=0;
k=0;
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("Could not open file %s",filename);
// return 1;
}
// this while-statement assigns into c, and then checks against EOF:
while((c = fgetc(fp)) != EOF)
{
if (c == '=')
{
if (k > 2) j++;
for(i=0;i < 10;i++)
{
dest[i]= 0;
}
i=0;
while((c = fgetc(fp)) != ';')
{
dest[i]= c;
i++;
}
val = atoi(dest);
val1 =(Type)val;
// printf("j = %d", j);
if (k>(C-1)) k=0;
// printf(" k = %d\n", k);
// printf("String value = %s\n", dest);
// printf("Int value = %d\n", val);
// printf("Type value = %.2f\n", val1);
// printf("\n");
A[C*j+k]=val1;
k++;
}
}
fclose(fp);
//-------------
/*
for (i=0;i < R;i++)
{
for (j=0;j < C;j++)
{
printf(" Matrix DF = %.4f\n", A[C*i+j]);
}
}
printf("\n\n");
// return 0;
*/
//------------
}
//**********************************************************************************
//******* Matrix-Vector Multiplication Routine **********************************
// V = A*U
void MatrixMathMatrixVectorMultiply(Type* A, Type* U, int m, int p, Type* V)
{
// A = input matrix A(rows x cols)
// U = input vector U(rows)
// V = output vector V(rows)= A(rows x cols)*U(rows)
// m = number of rows in A
// p = number of columns in A = number of rows in U
// V = output vector = A*U(m)
int i, j, k;
Type Ah[m][p]; //hulp array
Type Uh[p]; //hulp input vector
Type Vh[p];
for (i=0;i < m;i++)
{
for(j=0;j < p;j++)
{
Ah[i][j] = A[p*i+j];
}
}
for(j=0;j < p;j++)
{
Uh[j] = U[j];
// printf("\t%10.6f", Uh[j]);
// printf("\n");
}
for (i=0;i < m;i++)
{
V[i]=0;
for (k=0;k < p;k++)
{
V[i]+= Ah[i][k]*Uh[k];
}
}
/*
printf("\n");
for (i=0;i < p;i++)
{
printf("\t%.1f", V[i]);
printf("\n");
}
*/
}
//************* Matrix Inversion Routine *****************************************
// * This function inverts a matrix based on the Gauss Jordan method.
// * Specifically, it uses partial pivoting to improve numeric stability.
// * The algorithm is drawn from those presented in
// NUMERICAL RECIPES: The Art of Scientific Computing.
// * The function returns 1 on success, 0 on failure.
// * NOTE: The argument is ALSO the result matrix, meaning the input matrix is REPLACED
int MatrixMathInvert(Type* A, int n)
{
// A = input matrix AND result matrix
// n = number of rows = number of columns in A (n x n)
int pivrow; // keeps track of current pivot row
int k,i,j; // k: overall index along diagonal; i: row index; j: col index
int pivrows[n]; // keeps track of rows swaps to undo at end
Type tmp; // used for finding max value and making column swaps}
/*
//printf("\n");
printf("The Matrix to be inverted with Gauss-Jordan is: \n");
for (i=0;i < n;i++)
{
for(j=0;j < n;j++)
{
printf("%.4f", A[n*i+j]);
printf(" ");
}
printf("\n");
}
*/
for (k = 0; k < n; k++)
{
// find pivot row, the row with biggest entry in current column
tmp = 0;
for (i = k; i < n; i++)
{
if (abs(A[i*n+k]) >= tmp) // 'Avoid using other functions inside abs()?'
{
tmp = abs(A[i*n+k]);
pivrow = i;
//printf("%.4f\n", tmp);
}
}
// check for matrix singularity
if (A[pivrow*n+k] == 0.0f)
{
printf(" \n");
printf("Inversion failed due to singular matrix\n");
return 0;
}
// Execute pivot (row swap) if needed
if (pivrow != k)
{
// swap row k with pivrow
for (j = 0; j < n; j++)
{
tmp = A[k*n+j];
A[k*n+j] = A[pivrow*n+j];
A[pivrow*n+j] = tmp;
//printf("%lld\n", A[pivrow*n+j]);
}
}
pivrows[k] = pivrow; // record row swap (even if no swap happened)
tmp = 1.0f/A[k*n+k]; // invert pivot element
// tmp = A[k*n+k];
A[k*n+k] = 1.0f; // This element of input matrix becomes result matrix
//printf("%lld\n", A[k*n+k]);
//printf("%.8f\n", tmp);
// Perform row reduction (divide every element by pivot)
for (j = 0; j < n; j++)
{
A[k*n+j] = A[k*n+j]*tmp;
}
//OK
// Now eliminate all other entries in this column
for (i = 0; i < n; i++)
{
if (i != k)
{
tmp = A[i*n+k];
A[i*n+k] = 0.0;
for (j = 0; j < n; j++)
{
A[i*n+j] = A[i*n+j] - A[k*n+j]*tmp;
}
}
}
}
// Done, now need to undo pivot row swaps by doing column swaps in reverse order
for (k = n-1; k >= 0; k--)
{
if (pivrows[k] != k)
{
for (i = 0; i < n; i++)
{
tmp = A[i*n+k];
A[i*n+k] = A[i*n+pivrows[k]];
A[i*n+pivrows[k]] = tmp;
}
}
}
return 1;
}
//************* End Gauss-Jordan Matrix Inversion Function ********************
//******************** Start Gauss Eliminatiom Function ************************
void GaussElimination(Type* _aG, int row, int col)
{
// n=3= row, m=4= col;
// _aG = augmented input matrix (row x col)
Type aGh[row][col]; //hulp array
int i,j,k;
printf(" The augmented input matrix is: \n");
for (i=0; i < row; i++)
{
for(j=0; j < col; j++)
{
aGh[i][j] = _aG[col*i+j];
printf(" aGh[%d][%d]= %.6e",i,j,aGh[i][j]);
}
printf("\n");
}
for(i=0;i < n-1;i++)
{
if(aGh[i][i] == 0.0)
{
printf("Mathematical Error! _aG[%d][%d]= %.12f\n",i,i, aGh[i][i]);
exit(0);
}
for(j=i+1; j < n; j++)
{
// printf("\n\n aGh[%d][%d]= %.6e",j,i, aGh[j][i]);
// printf(" aGh[%d][%d]= %.6e\n",i,i,aGh[i][i]);
ratio = aGh[j][i]/aGh[i][i];
for(k=0; k < n+1; k++)
{
// printf("\n i= %d", i);
// printf(" j= %d", j);
// printf(" k= %d\n", k);
aGh[j][k] = aGh[j][k] - ratio * aGh[i][k];
// printf(" aGh[%d][%d]= %.6e",j,k,aGh[j][k]);
}
}
}
printf("\n");
printf(" The triangulized augmented input matrix is: \n");
for (i=0; i < row; i++)
{
for(j=0; j < col; j++)
{
// aGh[i][j] = _aG[col*i+j];
printf(" aGh[%d][%d]= %.6e",i,j,aGh[i][j]);
}
printf("\n");
}
// printf("\n");
// MatrixMathSciePrint((Type*) aGh,n,n,6,"The triangulized augmented input Matrix is: ");
printf("\n");
// printf(" n=%d",n);
// Calculate of eigenvector matrix (the matrix columns are the eigenvectors)
if( (abs(aGh[n-1][n-1]) || n>3) > 0.00000000001)
{
printf("Eigenvector Error! aGh[%d][%d]= %.12f\n",n,n, aGh[i][i]);
exit(0);
}
EiVec[0][l]= aGh[1][1] * aGh[0][2]/(aGh[0][0]*aGh[1][2])-aGh[0][1]/aGh[0][0];
EiVec[1][l]= 1;
EiVec[2][l]=-aGh[1][1]/aGh[1][2];
printf("\n");
}
//*********************** End Gauss Elimination Function *************************
// ***************** Start V2-Matrix Determinant Calc-Routine *****************
// Last Update: Bruno Best 09-7-20, 13:00 hrs
Type MatrixMathDeterminant(Type * _D, int _t)
{
// A = input matrix AND result matrix
// n = number of rows = number of columns in A (n x n)
int i, j;
Type _b[_row][_col];
Type res;
// printf("\n\n");
// printf("The SQUARE matrix for which the determinant is calculated is: \n");
for (i=0;i < _row;i++)
{
for(j=0;j < _col;j++)
{
_b[i][j] = _D[_row*i+j]; //load the to inverted data matrix
// printf("%.12f", _b[i][j]);
// printf(" ");
}
// printf("\n");
}
res= determinant(_b, _t);
return(res);
}
//--------------------------------------------------------------------------------------------
// ******************** Function to calculating Determinant of the Matrix ********************
Type determinant(Type _a[_row][_col], int _t)
{
Type s=1,det=0;
Type _d[_row][_col];
int i,j,m,n,c;
if (_t==1)
{
return (_a[0][0]);
}
else
{
det=0;
for (c=0;c < _t;c++)
{
m=0;
n=0;
for (i=0;i < _row;i++)
{
for (j=0;j < _col;j++)
{
_d[i][j]=0;
if (i != 0 && j != c)
{
// printf("%.6f", a[i][j]);
_d[m][n]=_a[i][j];
if (n < (_col-2))
n++;
else
{
n=0;
m++;
}
}
}
}
det=det + s * (_a[0][c] * determinant(_d,_t-1));
s=-1 * s;
}
}
return (det);
}
//***************** Matrix Printing Routine ************************************
// Uses tabs to separate numbers under assumption printed Type width won't cause problems
//void MatrixMathPrint(Type* A, int m, int n, int decimals, String label){
void MatrixMathPrint(Type* A, int row, int col, int decimals, char *Stringlabel)
{
// A = input matrix (row x col)
int i,j;
Type hval;
printf(" \n");
// print the string
while(*Stringlabel != '\0') {
printf("%c", *Stringlabel);
// move the ptr pointer to the next memory location
Stringlabel++;
}
printf(" \n");
for (i=0; i<row; i++){
for (j=0;j<col;j++){
hval=A[col*i+j];
printf("%+.*f", decimals, hval);
printf("\t");
}
printf(" \n");
}
}
//***************** Matrix Scientific Printing Routine **********************************
// Uses tabs to separate numbers under assumption printed Type width won't cause problems
//void MatrixMathSciePrint(Type* A, int m, int n, int decimals, String label)
void MatrixMathSciePrint(Type* A, int row, int col, int decimals, char *Stringlabel)
{
// A = input matrix (rows x cols)
int i,j;
Type hval;
printf(" \n");
// print the string
while(*Stringlabel != '\0') {
printf("%c", *Stringlabel);
// move the ptr pointer to the next memory location
Stringlabel++;
}
printf(" \n");
for (i=0; i<row; i++){
for (j=0;j<col;j++){
hval=A[col*i+j];
printf("%+.*f", decimals, hval);
printf("\t");
}
printf(" \n");
}
}
//*********** Copy Matrix Type to Type *****************************************
void MatrixMathCopy(Type* A, int row, int col, Type* B)
{
int i, j, k;
printf("\n");
for (i=0;i<row;i++)
{
for(j=0;j<col;j++)
{
B[col*i+j] = A[col*i+j];
// printf("%.6f", A[col*i+j]);
// printf(" %.6f", B[col*i+j]);
// printf("\t");
}
// printf("\n");
}
}
//************ Generate a I-Matrix ***************************************************
void MatrixMath_I_Matrix(Type* A, int row, int col)
{
int i, j;
for (i=0;i<row;i++)
for (j=0;j<col;j ++)
{
A[row*i+j]=0;
}
for (i=0;i<row;i ++)
{
A[row*i+i]=1;
}
}
//***************** Multiply Matrix with a CONSTANT ************************************
// void MatrixMath::Print(float* A, int m, int n, String label){
void MatrixMultiplyConstant(Type* A, Type* B, int row, int col, Type constant)
{
// A = input matrix (row x col)
int i,j;
for (i=0;i<row; i++){
for (j=0;j<col;j++){
B[col*i+j]= constant * A[col*i+j];
}
}
}
//******* Matrix Multiplication Routine **********************************
// C = A*B
void MatrixMathMultiply(Type* A, Type* B, int _p, int _r, int _q, Type* C)
{
// A = input matrix (m x p)
// B = input matrix (p x n)
// m = number of rows in A
// p = number of columns in A = number of rows in B
// n = number of columns in B
// C = output matrix = A*B (m x n)
int i, j, k;
for (i=0;i<_p;i++)
{
for(j=0;j<_q;j++)
{
C[_q*i+j]=0;
for (k=0;k<_r;k++)
{
C[_q*i+j]= C[_q*i+j]+ A[_r*i+k]* B[_q*k+j];
}
}
}
}
//*********** Matrix Transpose Routine ****************************************
//
void MatrixMathTranspose(Type* A, int row, int col, Type* C)
{
// A = input matrix (row x col)
// C = output matrix = the transpose of A (row x col)
int i, j;
for (i=0;i<row;i++)
for(j=0;j<col;j++)
C[row*j+i]=A[col*i+j];
}
//*********** Matrix Addition Routine ****************************************
void MatrixMathAddition(Type* A, Type* B, int row, int col, Type* C)
{
// A = input matrix (row x col)
// B = input matrix (row x col)
// C = output matrix = A-B (row x col)
int i, j;
for (i=0;i<row;i++)
for(j=0;j<col;j++)
C[col*i+j]=A[col*i+j]+B[col*i+j];
}
//*********** Matrix Subtraction Routine ****************************************
void MatrixMathSubtract(Type* A, Type* B, int row, int col, Type* C)
{
// A = input matrix (row x col)
// B = input matrix (row x col)
// C = output matrix = A-B (row x col)
int i, j;
for (i=0;i<row;i++){
for(j=0;j<col;j++){
C[row*i+j]=A[row*i+j]-B[row*i+j];
}
}
}
//***************** Export RawMag-Data to a GnuPlot-RAWData Text File *********************************
void exportRawMagdata2textfile(Type* A)
{
FILE *fp1;
float val;
int i;
char* filename = "d:\\Pelles C-SourceCode\\sensordata\\GnuPlot-RawData.txt";
char dest[50]; //26
char desth[15]; //10
char destk[15]; //10
char destl[15]; //10
i=0;
fp1 = fopen(filename, "w");
if (fp1 == NULL)
{
printf("Could not open file %s",filename);
// return 1;
exit(EXIT_FAILURE);
}
while(i < 3*R)
{
strcpy(dest, ""); //empty the dest String
val = A[i];
sprintf(desth, "%f%s", val, " , ");
strcat(dest, desth); // ;
i++;
val= A[i];
sprintf(destk, "%f%s", val, " , ");
strcat(dest, destk);
i++;
val= A[i];
sprintf(destl, "%f%s", val, "");
strcat(dest, destl);
i++;
// printf("Raw-Gnuplot-Data are: %s\n", dest);
fprintf(fp1,"%s\n", dest); // Write data to file
strcpy(dest, ""); //empty the dest String
}
// Close file to save file data
fclose(fp1);
printf("\n");
// Success message
printf("Raw-Data Gnu-Plot File is created and saved successfully. \n");
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
//************** Export Calibrated Mag-Data to a GnuPlot-CALIBData Text File *******
void exportCalibMagdata2textfile(Type* A)
{
FILE *fp1;
float val;
int i;
char* filename = "d:\\Pelles C-SourceCode\\sensordata\\GnuPlot-CalibData.txt";
char dest[50]; //26
char desth[15]; //10
char destk[15]; //10
char destl[15]; //10
i=0;
fp1 = fopen(filename, "w");
if (fp1 == NULL)
{
printf("Could not open file %s",filename);
// return 1;
exit(EXIT_FAILURE);
}
while(i < 3*R)
{
strcpy(dest, ""); //empty the dest String
val = A[i];
sprintf(desth, "%f%s", val, " , ");
strcat(dest, desth); // ;
i++;
val= A[i];
sprintf(destk, "%f%s", val, " , ");
strcat(dest, destk);
i++;
val= A[i];
sprintf(destl, "%f%s", val, "");
strcat(dest, destl);
i++;
// printf("Calb-Gnuplot-Data are: %s\n", dest);
fprintf(fp1,"%s\n", dest); // Write data to file
strcpy(dest, ""); //empty the dest String
}
// Close file to save file data
fclose(fp1);
// printf("\n");
// Success message
printf("Gnu-Plot file of calibrated measurements is created and saved successfully. \n");
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
//************** Export Final Mag-Calibration Results to a Text File **************
//Last update 28-12-2022
// * C program to create a file and write data to file.
void exportFinalCalibResults2textfile(void)
{
FILE *fp;
int val;
float valf;
char* filename = "d:\\Pelles C-SourceCode\\sensordata\\Final-Calib-Results.txt";
char dest[100];
char desth[20];
char destk[20];
char destl[20];
// const char str1[] = " ";
//-----------Converting Calibration to Sensor Config Format -----------
const char strWmin20[] = "// Sensor Calibration Data in Config Format.";
const char strVSxyz[] = "// x, y, z-Component of Hard-Iron Shift vector Mag_Vsi in bit-values is: ";
const char strVSx[] = " Mag_VSx = ";
const char strVSy[] = " Mag_VSy = ";
const char strVSz[] = " Mag_VSz = ";
fp = fopen(filename, "w");
if (fp == NULL)
{
printf("Could not open file %s",filename);
// return 1;
exit(EXIT_FAILURE);
}
fprintf(fp,"%s\n", strWmin20);
// time function
printf("\n");
time_t t = time(NULL);
struct tm *tm = localtime(&t);
fprintf(fp,"%s", asctime(tm));
fprintf(fp,"\n\n");
printf("%s\n", strVSxyz);
fprintf(fp,"%s\n", strVSxyz);
for (i=0;i < 3;i++)
{
dest[0]='\0';
if (i==0) strcat(dest, strVSx);
if (i==1) strcat(dest, strVSy);
if (i==2) strcat(dest, strVSz);
val=(int)VS[i];
sprintf(desth, "%d%s", val, ";");
strcat(dest, desth);
printf("%s\n", dest);
fprintf(fp,"%s\n", dest);
// dest[0]='\0';
strcpy(dest, "");
}
printf("\n\n");
fprintf(fp,"\n\n");
//---------------------------------------------------
const char strWmin1[] = "// The Mag-Calibration Matrix Wmin1 or W**-1=sqrt(A[3x3]) is: !!!!!";
printf("%s\n", strWmin1);
fprintf(fp,"%s\n", strWmin1);
printf("\n");
fprintf(fp,"\n");
const char strWmin1_0[] = "// First row of Wmin1 MagCTp row=0";
printf("%s\n", strWmin1_0);
fprintf(fp,"%s\n", strWmin1_0);
const char strWmin1_0_0[] = " Wmin1[0][0] = ";
const char strWmin1_0_1[] = " Wmin1[0][1] = ";
const char strWmin1_0_2[] = " Wmin1[0][2] = ";
for (i=0;i < 3;i++)
{
dest[0]='\0';
if (i==0) strcat(dest, strWmin1_0_0);
if (i==1) strcat(dest, strWmin1_0_1);
if (i==2) strcat(dest, strWmin1_0_2);
valf=Wmin1[i][0];
sprintf(desth, "%e%s", valf, ";");
strcat(dest, desth);
printf("%s\n", dest);
fprintf(fp,"%s\n", dest);
// dest[0]='\0';
strcpy(dest, "");
}
printf("\n");
fprintf(fp,"\n");
const char strWmin1_1[] = "// Second row of Wmin1 MagCTp row=1";
printf("%s\n", strWmin1_1);
fprintf(fp,"%s\n", strWmin1_1);
const char strWmin1_1_0[] = " Wmin1[1][0] = ";
const char strWmin1_1_1[] = " Wmin1[1][1] = ";
const char strWmin1_1_2[] = " Wmin1[1][2] = ";
for (i=0;i < 3;i++)
{
dest[0]='\0';
if (i==0) strcat(dest, strWmin1_1_0);
if (i==1) strcat(dest, strWmin1_1_1);
if (i==2) strcat(dest, strWmin1_1_2);
valf=Wmin1[i][1];
sprintf(desth, "%e%s", valf, ";");
strcat(dest, desth);
printf("%s\n", dest);
fprintf(fp,"%s\n", dest);
// dest[0]='\0';
strcpy(dest, "");
}
printf("\n");
fprintf(fp,"\n");
const char strWmin1_2[] = "// Third row of Wmin1 MagCTp row=2";
printf("%s\n", strWmin1_2);
fprintf(fp,"%s\n", strWmin1_2);
const char strWmin1_2_0[] = " Wmin1[2][0] = ";
const char strWmin1_2_1[] = " Wmin1[2][1] = ";
const char strWmin1_2_2[] = " Wmin1[2][2] = ";
for (i=0;i < 3;i++)
{
dest[0]='\0';
if (i==0) strcat(dest, strWmin1_2_0);
if (i==1) strcat(dest, strWmin1_2_1);
if (i==2) strcat(dest, strWmin1_2_2);
valf=Wmin1[i][2];
sprintf(desth, "%e%s", valf, ";");
strcat(dest, desth);
printf("%s\n", dest);
fprintf(fp,"%s\n", dest);
// dest[0]='\0';
strcpy(dest, "");
}
printf("\n\n");
fprintf(fp,"\n\n");
// Close file to save file data
fclose(fp);
// Success message with Date and Time
printf("Final Calibration Results saved successfully to file 'Final-Calib-Results.txt' \n");
printf("%s\n", asctime(tm));
}
////**** End Sec2 Calib.Utility 4: Magnetometer Calibration ****