我正在尝试使用FireMonkey
构建一个多设备的磁罗经应用程序。
如何获得倾斜补偿的磁航向?
答案 0 :(得分:4)
在iOS上,可从OS获得倾斜补偿的磁航向。 TiOSLocationSensor(GPS)实时提供MagneticHeading和TrueHeading。
在Android上,MagneticHeading大多数时候都是NaN,或者有一个值,但不是实时的。因此,AFAIK必须通过加速度计+磁力计读数来计算。
倾斜补偿意味着电话可以倾斜(俯仰和滚动<> 0)而不会影响航向(偏航角)。加速度计读数用于旋转磁矢量。默认的航向角在XZ平面内(即手机或多或少处于垂直位置)。如果手机为横向,则航向为YZ平面,并且必须相应地旋转轴。
// this function x,y,z axis for the phone in vertical orientation (portrait)
function calcTiltCompensatedMagneticHeading(const {acel}aGx,aGy,aGz,{mag} aMx,aMy,aMz:double ):double; //return heading in degrees
var Phi,Theta,cosPhi,sinPhi,Gz2,By2,Bz2,Bx3:Double;
begin
Result := NaN; //=invalid
// https://www.st.com/content/ccc/resource/technical/document/design_tip/group0/56/9a/e4/04/4b/6c/44/ef/DM00269987/files/DM00269987.pdf/jcr:content/translations/en.DM00269987.pdf
Phi := ArcTan2(aGy,aGz); //calc Roll (Phi)
cosPhi := Cos(Phi); //memoise phi trigs
sinPhi := Sin(Phi);
Gz2 := aGy*sinPhi+aGz*cosPhi;
if (Gz2<>0) then
begin
Theta := Arctan(-aGx/Gz2); // Theta = Pitch
By2 := aMz * sinPhi - aMy * cosPhi;
Bz2 := aMy * sinPhi + aMz * cosPhi;
Bx3 := aMx * Cos(Theta) + Bz2 * Sin(Theta);
Result := ArcTan2(By2,Bx3)*180/Pi-90; //convert to degrees and then add 90 for North based heading (Psi)
end;
end;
//usage
{$IFDEF ANDROID}
mx := MagSensor1.HeadingX; //in mTeslas
my := MagSensor1.HeadingY;
mz := MagSensor1.HeadingZ;
aGx := MotionSensor1.Sensor.AccelerationX; //get acceleration sensor
aGy := MotionSensor1.Sensor.AccelerationY;
aGz := MotionSensor1.Sensor.AccelerationZ;
aMagHeading:=0;
if IsLandscapeMode then //landscape phone orientation
begin
aMagHeading := calcTiltCompensatedMagneticHeading({acel}aGy,-aGx,aGz,{mag} my,-mx,mz); //rotated 90 in z axis
end
else begin //portrait orientation
aMagHeading := calcTiltCompensatedMagneticHeading({acel}aGx,aGy,aGz,{mag} mx,my,mz); // normal portrait orientation
end;
{$ENDIF ANDROID}