Herelink IMU / Compass

Hi,

I’m trying to calculate the orientation between the RC and the UAV. For that, I require the orientation of the RC. I’ve developed code that works on Android, but it’s not working on the herelink. When debugging, I’m not getting any sensor data (magneticSensor and accelerometerSensor)

Any idea what might be causing this? Any thing I need to change?

Code bellow:

public class HerelinkGeolocationPlugin extends CordovaPlugin {
public static final String TAG = "HerelinkGeolocationPlu";

CallbackContext context;

String [] permissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION };

int getPermissionRequestCode = 0;
int watchRequestCode = 1;
private SensorManager sensorManager;

double mOrientation = 0.0;

@Override
public void onDestroy() {
    super.onDestroy();
    if (sensorManager != null) {
        sensorManager.unregisterListener(listener);
    }
}

@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
    Log.d(TAG, "Geolocation Plugin Executing");
    context = callbackContext;
    if(action.equals("getPermission"))
    {
        if(hasPermisssion())
        {
            PluginResult r = new PluginResult(PluginResult.Status.OK);
            context.sendPluginResult(r);
            return true;
        }
        else {
            PermissionHelper.requestPermissions(this, this.getPermissionRequestCode, permissions);
        }
        return true;
    } else if (action.equals("watchLocation")) {
        this.requestPermissions(this.watchRequestCode);
        return true;
    }
    return false;
}

private void initSensorReading () {
    final Activity activity = cordova.getActivity();
    sensorManager = (SensorManager) activity.getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
    Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_NORMAL);
    sensorManager.registerListener(listener, accelerometerSensor,SensorManager.SENSOR_DELAY_NORMAL);
}

private SensorEventListener listener = new SensorEventListener() {
    float[] accelerometerValues = new float[3];
    float[] magneticValues = new float[3];
    @Override
    public void onSensorChanged(SensorEvent event) {
        // Determine whether it is an acceleration sensor or a geomagnetic sensor
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            // Pay attention to call the clone() method when assigning
            accelerometerValues = event.values.clone();
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            magneticValues = event.values.clone();
        }
        float[] R = new float[9];
        float[] values = new float[3];
        SensorManager.getRotationMatrix(R, null, accelerometerValues,
            magneticValues);
        SensorManager.getOrientation(R, values);
        mOrientation = Math.toDegrees(values[0]);
        Log.d(TAG, "mOrientation: " + mOrientation);

    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }



};


public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException
{
    PluginResult result;
    Log.d(TAG, "Request Code: " + requestCode);
    //This is important if we're using Cordova without using Cordova, but we have the geolocation plugin installed
    if(context != null) {
        for (int r : grantResults) {
            Log.d(TAG, "result : " + r);
            if (r == PackageManager.PERMISSION_DENIED) {
                Log.d(TAG, "Permission Denied!");
                result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
                context.sendPluginResult(result);
                return;
            }
        }
        if (requestCode == this.watchRequestCode){
            this.watchLocation(context);
            return;
        }
        result = new PluginResult(PluginResult.Status.OK);
        result.setKeepCallback(true);
        context.sendPluginResult(result);

    }
}

public boolean hasPermisssion() {
    for(String p : permissions)
    {
        if(!PermissionHelper.hasPermission(this, p))
        {
            return false;
        }
    }
    return true;
}

/*
 * We override this so that we can access the permissions variable, which no longer exists in
 * the parent class, since we can't initialize it reliably in the constructor!
 */
public void requestPermissions(int requestCode)
{
    PermissionHelper.requestPermissions(this, requestCode, permissions);
}

private boolean debugBool = true;

// Permission is checked before trying to create location listener
@SuppressLint("MissingPermission")
public boolean watchLocation(CallbackContext callbackContext) {
    if(!hasPermisssion())
    {
        PermissionHelper.requestPermissions(this, 0, permissions);
    }
    Context context = this.cordova.getContext();
    LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    boolean hasGps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    if(debugBool) {
        this.initSensorReading();
        debugBool = false;
    }

    LocationListener gpsLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            Log.d(TAG, location.toString());
            JSONObject json = new JSONObject();
            try {

                json.put("altitude", location.getAltitude());
                json.put("longitude", location.getLongitude());
                json.put("latitude", location.getLatitude());
                json.put("speed", location.getSpeed());
                json.put("bearing", mOrientation == 0.0 ? location.getBearing() : mOrientation);
                PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, json);
                pluginResult.setKeepCallback(true);
                callbackContext.sendPluginResult(pluginResult);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.d(TAG, "Status Changed");
        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.d(TAG, "Provider Enabled");
        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.d(TAG, "Provider Disabled");
        }
    };

    if (hasGps) {
        locationManager.requestLocationUpdates(
            LocationManager.GPS_PROVIDER,
            250,
            0F,
            gpsLocationListener
        );
        return true;
    } else {
        PluginResult pluginResult = new PluginResult(PluginResult.Status.ERROR, "Failed to get GPS");
        callbackContext.sendPluginResult(pluginResult);
        return false;
    }

}

}

There are no internal IMU in Herelink. I don’t think you can get such data from it.

You sure Alvin? I had the idea that the Android screen/phone you’re using to build the Herelink, had it embedded.

Do you know any other way to get the RC orientation?

I’ve managed to get it from the GPS data (bearing variation), but the error is really big…

May I know where did you get this information?

Herelink is using a Pinecone S1, and similar integrations as the Xiaomi Mi5C. And these have the typical sensors on a phone.

Can’t recall from which website a I got this info.

Yes Herelink is using Pinecone S1, but that is the processor. IMU is a different chip.
You can’t say it contains IMU just because it shares the same processor with an IMU-onboarded phone.

You’re right. Probably read it somewhere in the forum,and mixed the concepts.