oculus1

diff libovr/Src/Util/Util_MagCalibration.cpp @ 1:e2f9e4603129

added LibOVR and started a simple vr wrapper.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Sep 2013 16:14:59 +0300
parents
children b069a5c27388
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libovr/Src/Util/Util_MagCalibration.cpp	Sat Sep 14 16:14:59 2013 +0300
     1.3 @@ -0,0 +1,1 @@
     1.4 +/************************************************************************************
     1.5 
     1.6 Filename    :   Util_MagCalibration.cpp
     1.7 Content     :   Procedures for calibrating the magnetometer
     1.8 Created     :   April 16, 2013
     1.9 Authors     :   Steve LaValle, Andrew Reisse
    1.10 
    1.11 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
    1.12 
    1.13 Use of this software is subject to the terms of the Oculus license
    1.14 agreement provided at the time of installation or download, or which
    1.15 otherwise accompanies this software in either electronic or hard copy form.
    1.16 
    1.17 *************************************************************************************/
    1.18 
    1.19 #include "Util_MagCalibration.h"
    1.20 
    1.21 namespace OVR { namespace Util {
    1.22 
    1.23 void MagCalibration::BeginAutoCalibration(SensorFusion& sf)
    1.24 {
    1.25     Stat = Mag_AutoCalibrating;
    1.26     // This is a "hard" reset of the mag, so need to clear stored values
    1.27     sf.ClearMagCalibration();
    1.28     SampleCount = 0;
    1.29 
    1.30     // reset the statistics
    1.31     MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f);
    1.32     MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f);
    1.33 	MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f);
    1.34 	MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f);
    1.35 }
    1.36 
    1.37 unsigned MagCalibration::UpdateAutoCalibration(SensorFusion& sf)
    1.38 {
    1.39     if (Stat != Mag_AutoCalibrating)
    1.40         return Stat;
    1.41 
    1.42     Quatf q = sf.GetOrientation();
    1.43     Vector3f m = sf.GetMagnetometer();
    1.44 
    1.45     InsertIfAcceptable(q, m);
    1.46 
    1.47     if ((SampleCount == 4) && (Stat == Mag_AutoCalibrating))
    1.48 	{
    1.49 		//LogText("Magnetometer Output Spread: %f %f %f\n",MagSpread.x,MagSpread.y,MagSpread.z);
    1.50 		//LogText("Quaternion Spread: %f %f %f %f\n",QuatSpread.x,QuatSpread.y,QuatSpread.z,QuatSpread.w);
    1.51         SetCalibration(sf);
    1.52 	}
    1.53 
    1.54     return Stat;
    1.55 
    1.56 }
    1.57 
    1.58 void MagCalibration::BeginManualCalibration(SensorFusion& sf)
    1.59 {
    1.60     Stat = Mag_ManuallyCalibrating;
    1.61     sf.ClearMagCalibration();
    1.62     SampleCount = 0;
    1.63 }
    1.64 
    1.65 bool MagCalibration::IsAcceptableSample(const Quatf& q, const Vector3f& m)
    1.66 {
    1.67     switch (SampleCount)
    1.68     {
    1.69         // Initial sample is always acceptable
    1.70     case 0:
    1.71         return true;
    1.72         break;
    1.73     case 1:
    1.74         return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&&
    1.75                ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq);
    1.76         break;
    1.77     case 2:
    1.78         return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&&
    1.79                (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&&
    1.80                ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq)&&
    1.81                ((m - MagSamples[1]).LengthSq() > MinMagDistanceSq);
    1.82         break;
    1.83     case 3:
    1.84         return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&&
    1.85                (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&&
    1.86                (q.DistanceSq(QuatSamples[2]) > MinQuatDistanceSq)&&
    1.87                ((PointToPlaneDistance(MagSamples[0],MagSamples[1],MagSamples[2],m) > MinMagDistance)||
    1.88                 (PointToPlaneDistance(MagSamples[1],MagSamples[2],m,MagSamples[0]) > MinMagDistance)||
    1.89                 (PointToPlaneDistance(MagSamples[2],m,MagSamples[0],MagSamples[1]) > MinMagDistance)||
    1.90                 (PointToPlaneDistance(m,MagSamples[0],MagSamples[1],MagSamples[2]) > MinMagDistance));
    1.91     }
    1.92 
    1.93     return false;
    1.94 }
    1.95 
    1.96 
    1.97 bool MagCalibration::InsertIfAcceptable(const Quatf& q, const Vector3f& m)
    1.98 {
    1.99 	// Update some statistics
   1.100 	if (m.x < MinMagValues.x)
   1.101 		MinMagValues.x = m.x;
   1.102 	if (m.y < MinMagValues.y)
   1.103 		MinMagValues.y = m.y;
   1.104 	if (m.z < MinMagValues.z)
   1.105 		MinMagValues.z = m.z;
   1.106 	if (m.x > MaxMagValues.x)
   1.107 		MaxMagValues.x = m.x;
   1.108 	if (m.y > MaxMagValues.y)
   1.109 		MaxMagValues.y = m.y;
   1.110 	if (m.z > MaxMagValues.z)
   1.111 		MaxMagValues.z = m.z;
   1.112 	if (q.x < MinQuatValues.x)
   1.113 		MinQuatValues.x = q.x;
   1.114 	if (q.y < MinQuatValues.y)
   1.115 		MinQuatValues.y = q.y;
   1.116 	if (q.z < MinQuatValues.z)
   1.117 		MinQuatValues.z = q.z;
   1.118 	if (q.w < MinQuatValues.w)
   1.119 		MinQuatValues.w = q.w;
   1.120 	if (q.x > MaxQuatValues.x)
   1.121 		MaxQuatValues.x = q.x;
   1.122 	if (q.y > MaxQuatValues.y)
   1.123 		MaxQuatValues.y = q.y;
   1.124 	if (q.z > MaxQuatValues.z)
   1.125 		MaxQuatValues.z = q.z;
   1.126 	if (q.w > MaxQuatValues.w)
   1.127 		MaxQuatValues.w = q.w;
   1.128 	MagSpread = MaxMagValues - MinMagValues;
   1.129 	QuatSpread = MaxQuatValues - MinQuatValues;
   1.130 
   1.131 	if (IsAcceptableSample(q, m))
   1.132     {
   1.133         MagSamples[SampleCount] = m;
   1.134         QuatSamples[SampleCount] = q;
   1.135         SampleCount++;
   1.136         return true;
   1.137     }
   1.138 
   1.139     return false;
   1.140 }
   1.141 
   1.142 Matrix4f MagCalibration::GetMagCalibration() const
   1.143 {
   1.144     Matrix4f calMat = Matrix4f();
   1.145     calMat.M[0][3] = -MagCenter.x;
   1.146     calMat.M[1][3] = -MagCenter.y;
   1.147     calMat.M[2][3] = -MagCenter.z;
   1.148     return calMat;
   1.149 }
   1.150 
   1.151 bool MagCalibration::SetCalibration(SensorFusion& sf)
   1.152 {
   1.153     if (SampleCount < 4)
   1.154         return false;
   1.155 
   1.156     MagCenter = CalculateSphereCenter(MagSamples[0],MagSamples[1],MagSamples[2],MagSamples[3]);
   1.157     Matrix4f calMat = GetMagCalibration();
   1.158     sf.SetMagCalibration(calMat);
   1.159     Stat = Mag_Calibrated;
   1.160     //LogText("MagCenter: %f %f %f\n",MagCenter.x,MagCenter.y,MagCenter.z);
   1.161 
   1.162     return true;
   1.163 }
   1.164 
   1.165 
   1.166 // Calculate the center of a sphere that passes through p1, p2, p3, p4
   1.167 Vector3f MagCalibration::CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2,
   1.168                                                const Vector3f& p3, const Vector3f& p4) 
   1.169 {
   1.170     Matrix4f A;
   1.171     int i;
   1.172     Vector3f p[4];
   1.173     p[0] = p1;
   1.174     p[1] = p2;
   1.175     p[2] = p3;
   1.176     p[3] = p4;
   1.177 
   1.178     for (i = 0; i < 4; i++) 
   1.179     {
   1.180         A.M[i][0] = p[i].x;
   1.181         A.M[i][1] = p[i].y;
   1.182         A.M[i][2] = p[i].z;
   1.183         A.M[i][3] = 1.0f;
   1.184     }
   1.185     float m11 = A.Determinant();
   1.186     OVR_ASSERT(m11 != 0.0f);
   1.187 
   1.188     for (i = 0; i < 4; i++) 
   1.189     {
   1.190         A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z;
   1.191         A.M[i][1] = p[i].y;
   1.192         A.M[i][2] = p[i].z;
   1.193         A.M[i][3] = 1.0f;
   1.194     }
   1.195     float m12 = A.Determinant();
   1.196 
   1.197     for (i = 0; i < 4; i++) 
   1.198     {
   1.199         A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z;
   1.200         A.M[i][1] = p[i].x;
   1.201         A.M[i][2] = p[i].z;
   1.202         A.M[i][3] = 1.0f;
   1.203     }
   1.204     float m13 = A.Determinant();
   1.205 
   1.206     for (i = 0; i < 4; i++) 
   1.207     {
   1.208         A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z;
   1.209         A.M[i][1] = p[i].x;
   1.210         A.M[i][2] = p[i].y;
   1.211         A.M[i][3] = 1.0f;
   1.212     }
   1.213     float m14 = A.Determinant();
   1.214 
   1.215     float c = 0.5f / m11;
   1.216     return Vector3f(c*m12, -c*m13, c*m14);
   1.217 }
   1.218 
   1.219 // Distance from p4 to the nearest point on a plane through p1, p2, p3
   1.220 float MagCalibration::PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2,
   1.221                                            const Vector3f& p3, const Vector3f& p4) 
   1.222 {
   1.223     Vector3f v1 = p1 - p2;
   1.224     Vector3f v2 = p1 - p3;
   1.225     Vector3f planeNormal = v1.Cross(v2);
   1.226     planeNormal.Normalize();
   1.227     return (fabs((planeNormal * p4) - planeNormal * p1));
   1.228 }
   1.229 
   1.230 }}
   1.231 \ No newline at end of file