如何使用FireMonkey进行倾斜补偿的磁航向?

时间:2018-10-18 16:24:06

标签: delphi firemonkey

我正在尝试使用FireMonkey构建一个多设备的磁罗经应用程序。 如何获得倾斜补偿的磁航向?

1 个答案:

答案 0 :(得分:4)

在iOS上,可从OS获得倾斜补偿的磁航向。 TiOSLocationSensor(GPS)实时提供MagneticHeading和TrueHeading。

在Android上,MagneticHeading大多数时候都是NaN,或者有一个值,但不是实时的。因此,AFAIK必须通过加速度计+磁力计读数来计算。

倾斜补偿意味着电话可以倾斜(俯仰和滚动<> 0)而不会影响航向(偏航角)。加速度计读数用于旋转磁矢量。默认的航向角在XZ平面内(即手机或多或少处于垂直位置)。如果手机为横向,则航向为YZ平面,并且必须相应地旋转轴。

我从
那里得到了公式 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

// 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}