iOS Question Motion object does not give me what I need

JackKirk

Well-Known Member
Licensed User
Hi,

I'm porting a B4A app to B4i.

The B4A app uses raw total acceleration (user + gravity), raw gyroscope and calibrated magnetometer (i.e. raw but with device bias adjusted out) data and an indicator of magnetometer calibration (un-, low, medium, high).

I think I have pretty well worked out how to do what I want with the Motion object as a base - except for the magnetometer - I can't work out how to get it started.

My test bed code is (zip at bottom):
B4X:
'Code module
#Region  Project Attributes
    #ApplicationLabel: B4i Example
    #Version: 1.0.0
    'Orientation possible values: Portrait, LandscapeLeft, LandscapeRight AND PortraitUpsideDown
    #iPhoneOrientations: Portrait
    #iPadOrientations: Portrait
  
#End Region

Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page
    Private mot As Motion
    Private timer1 As Timer
    Private bbStart, bbStop As BarButton
    Private lblAtt As Label
    Private lblAttPitch As Label
    Private lblAttRoll As Label
    Private lblAttYaw As Label
    Private lblTot_Accel As Label
    Private lblTot_AccelX As Label
    Private lblTot_AccelY As Label
    Private lblTot_AccelZ As Label
    Private lblTot_AccelX_max As Label
    Private lblTot_AccelY_max As Label
    Private lblTot_AccelZ_max As Label
    Private lblTot_AccelX_min As Label
    Private lblTot_AccelY_min As Label
    Private lblTot_AccelZ_min As Label
    Private lblGyro As Label
    Private lblGyroX As Label
    Private lblGyroY As Label
    Private lblGyroZ As Label
    Private lblMag As Label
    Private lblMagAcc As Label
    Private lblMagX As Label
    Private lblMagY As Label
    Private lblMagZ As Label
    Private tot_accel_max(3) As Double
    Private tot_accel_min(3) As Double
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.RootPanel.LoadLayout("1")
    NavControl.ShowPage(Page1)
    mot.Initialize
    timer1.Initialize("timer1", 100)
    bbStart = Page1.TopRightButtons.Get(0)  
    bbStop = Page1.TopRightButtons.Get(1)
End Sub

Sub Page1_BarButtonClick (Tag As String)
    If Tag = "Start" Then
        timer1.Enabled = True
        mot.Start
        mot.StartMagnetometer
    Else
        timer1.Enabled = False
        mot.Stop
        mot.StopMagnetometer
    End If
    bbStart.Enabled = Not(timer1.Enabled)
    bbStop.Enabled = timer1.Enabled
End Sub

Sub Timer1_Tick
    Dim attitude() As Double = mot.GetAttitude
    Dim tot_accel_val(3) As Double
    Dim gyro_val(3) As Double
    Dim magfld_val(3) As Double

    lblAttYaw.Text = "yaw: " & NumberFormat(attitude(0) * 180 / cPI, 1, 2) & Chr(0xB0)
    lblAttPitch.Text = "pitch: " &  NumberFormat(attitude(1) * 180 / cPI, 1, 2) & Chr(0xB0)
    lblAttRoll.Text = "roll: " &  NumberFormat(attitude(2) * 180 / cPI, 1, 2) & Chr(0xB0)

    Dim no As NativeObject = Me
    Dim accel As List = no.RunMethod("getAcceleration:", Array(mot))
    Dim gravity As List = no.RunMethod("getGravity:", Array(mot))
    tot_accel_val(0) = gravity.Get(0) + accel.Get(0)
    tot_accel_val(1) = gravity.Get(1) + accel.Get(1)
    tot_accel_val(2) = gravity.Get(2) + accel.Get(2)
    lblTot_AccelX.Text = NumberFormat(tot_accel_val(0), 1, 4) & "g"
    lblTot_AccelY.Text = NumberFormat(tot_accel_val(1), 1, 4) & "g"
    lblTot_AccelZ.Text = NumberFormat(tot_accel_val(2), 1, 4) & "g"
    tot_accel_max(0) = Max(tot_accel_max(0), tot_accel_val(0))
    tot_accel_min(0) = Min(tot_accel_min(0), tot_accel_val(0))
    tot_accel_max(1) = Max(tot_accel_max(1), tot_accel_val(1))
    tot_accel_min(1) = Min(tot_accel_min(1), tot_accel_val(1))
    tot_accel_max(2) = Max(tot_accel_max(2), tot_accel_val(2))
    tot_accel_min(2) = Min(tot_accel_min(2), tot_accel_val(2))
    lblTot_AccelX_max.Text = NumberFormat(tot_accel_max(0), 1, 4) & "g"
    lblTot_AccelY_max.Text = NumberFormat(tot_accel_max(1), 1, 4) & "g"
    lblTot_AccelZ_max.Text = NumberFormat(tot_accel_max(2), 1, 4) & "g"
    lblTot_AccelX_min.Text = NumberFormat(tot_accel_min(0), 1, 4) & "g"
    lblTot_AccelY_min.Text = NumberFormat(tot_accel_min(1), 1, 4) & "g"
    lblTot_AccelZ_min.Text = NumberFormat(tot_accel_min(2), 1, 4) & "g"

    Dim gyro As List = no.RunMethod("getGyro:", Array(mot))
    gyro_val(0) = gyro.Get(0)
    gyro_val(1) = gyro.Get(1)
    gyro_val(2) = gyro.Get(2)
    lblGyroX.Text = NumberFormat(gyro_val(0) * 180 / cPI, 1, 4) & Chr(0xB0) & "/s"
    lblGyroY.Text = NumberFormat(gyro_val(1) * 180 / cPI, 1, 4) & Chr(0xB0) & "/s"
    lblGyroZ.Text = NumberFormat(gyro_val(2) * 180 / cPI, 1, 4) & Chr(0xB0) & "/s"
  
    Try

        Dim magfld As List = no.RunMethod("getMagField:", Array(mot))
        magfld_val(0) = magfld.Get(0)
        magfld_val(1) = magfld.Get(1)
        magfld_val(2) = magfld.Get(2)
        lblMagX.Text = NumberFormat(magfld_val(0), 1, 2) & "uT"
        lblMagY.Text = NumberFormat(magfld_val(1), 1, 2) & "uT"
        lblMagZ.Text = NumberFormat(magfld_val(2), 1, 2) & "uT"

        Dim magacc As List = no.RunMethod("getMagAccuracy:", Array(mot))
        lblMagAcc.Text = magacc.get(0)
    '    @Generated Public static final int Uncalibrated = 0xFFFFFFFF (-1);
    '    @Generated Public static final int Low = 0x00000000 (0);
    '    @Generated Public static final int Medium = 0x00000001 (1);
    '    @Generated Public static final int High = 0x00000002 (2);

    Catch
    End Try
End Sub

#if OBJC
- (NSArray*) getAcceleration: (CMMotionManager*) manager {
    CMDeviceMotion *motion = manager.deviceMotion;
    CMAcceleration acc = motion.userAcceleration;
    return @[@(acc.x), @(acc.y), @(acc.z)];
}
#end if

#if OBJC
- (NSArray*) getGravity: (CMMotionManager*) manager {
    CMDeviceMotion *motion = manager.deviceMotion;
    CMAcceleration grv = motion.gravity;
    return @[@(grv.x), @(grv.y), @(grv.z)];
}
#end if

#if OBJC
- (NSArray*) getGyro: (CMMotionManager*) manager {
    CMDeviceMotion *motion = manager.deviceMotion;
    CMRotationRate gyr = motion.rotationRate;
    return @[@(gyr.x), @(gyr.y), @(gyr.z)];
}
#end if

#if OBJC
- (NSArray*) getMagField: (CMMotionManager*) manager {
    CMDeviceMotion *motion = manager.deviceMotion;
    CMCalibratedMagneticField magfld = motion.magneticField;
    return @[@(magfld.field.x), @(magfld.field.y), @(magfld.field.z)];
}
#end if

#if OBJC
- (NSArray*) getMagAccuracy: (CMMotionManager*) manager {
    CMDeviceMotion *motion = manager.deviceMotion;
    CMCalibratedMagneticField magfld = motion.magneticField;
    return @[@(magfld.accuracy)];
}
#end if
Any help appreciated....
 

Attachments

JackKirk

Well-Known Member
Licensed User
Erel,
1. Note that you don't need to create a separate OBJC section for each method. You can use a single one with all the code.
A measure of my very limited Objective C skills - but really beside the point.

2. Never catch an error without a log message. It will only make it harder for you to understand what happens.
I forget now why I put this there.

I just commented it out this end and it now makes no difference.

If you run the code you will see that I do not get Magnetometer values as I believe I should - could you give me some guidance of how to start Magnetometer to get calibrated values and accuracy with objective C - I have been crawling all over google without success.

Thanks...
 
Top