How to add mavlink items


#1

I have my drone set up to run a mavlink file. Everything works great, up to and including take-off. Then the drone starts randomly drifting around for an extended period of time.

All I want to do is send it to a couple locations and back again.

This is my Java code (lat and lng are the GPS coordinates returned by the drone on connect):

list = new ArrayList<>();
list.add(ARMavlinkMissionItem.CreateMavlinkDelay(10));
list.add(ARMavlinkMissionItem.CreateMavlinkTakeoffMissionItem(lat,lng, alt,(float)1.5, 0));
list.add(ARMavlinkMissionItem.CreateMavlinkNavWaypointMissionItem((float)35.0093, (float)-101.595,(float)1.5, 0));
list.add(ARMavlinkMissionItem.CreateMavlinkNavWaypointMissionItem((float)35.0097,(float)-101.592,(float)1.5, 0));
list.add(ARMavlinkMissionItem.CreateMavlinkLandMissionItem(lat,lng, 0, 0));

I assume there’s something wrong here, but I have no idea what. Does anybody know why this thing isn’t working? Are there any online examples of a simple Mavlink mission?


#2

you’re doing it wrong :slight_smile:

    public String generateMavlinkFile() {

        ...

        final ARMavlinkFileGenerator generator;

        try {
            generator = new ARMavlinkFileGenerator();
        } catch (ARMavlinkException e) {
            Log.e(CLASS_NAME, "generateMavlinkFile: " + e.getMessage(), e);
            return "";
        }

        generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkDelay(10));
        generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkTakeoffMissionItem(lat,lng, alt,(float)1.5, 0));
        generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkNavWaypointMissionItem((float)35.0093, (float)-101.595,(float)1.5, 0));
        generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkNavWaypointMissionItem((float)35.0097,(float)-101.592,(float)1.5, 0));
        generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkLandMissionItem(lat,lng, 0, 0));
        
        // save our mavlink file
        final File file = new File(MAVLINK_STORAGE_DIRECTORY);
        //noinspection ResultOfMethodCallIgnored
        file.mkdirs();

        final String filename = MAVLINK_STORAGE_DIRECTORY + File.separator + "flightPlan.mavlink";
        final File mavFile = new File(filename);

        //noinspection ResultOfMethodCallIgnored
        mavFile.delete();
        generator.CreateMavlinkFile(filename);

        return filename;
   }

#3

Hi Shell,

Your code seems quite effective. How would the C implementation of this look?

Currently I have the following however it is not quite producing the results I want:

mavlink_mission_item_t item;
eARMAVLINK_ERROR errorM;
ARMAVLINK_FileGenerator_t *generator =  ARMAVLINK_FileGenerator_New(&errorM);
errorM = ARMAVLINK_MissionItemUtils_CreateMavlinkTakeoffMissionItem(&item, 41.777217, -88.234855, 50, 180, 100);
errorM = ARMAVLINK_FileGenerator_AddMissionItem(generator, &item);
    
errorM = ARMAVLINK_MissionItemUtils_CreateMavlinkDelay(&item, 10);
errorM = ARMAVLINK_FileGenerator_AddMissionItem(generator, &item);
    
errorM = ARMAVLINK_MissionItemUtils_CreateMavlinkNavWaypointMissionItem(&item, 41.777855, -88.234908, 50, 0);
errorM = ARMAVLINK_FileGenerator_AddMissionItem(generator, &item);
    
ARMAVLINK_FileGenerator_CreateMavlinkFile(generator, "flightPlan.mavlink");

#4

Hi,

What do you mean by “it is not quite producing the results I want”?
You don’t check the returned error, maybe that can help.

Regards,
Djavan


#5

The following is my current error:

This occurs despite having #included libARMavlink/libARMavlink.h. Am I implementing this correctly?


#6

Hi!
Did you find a solution to that problem?


#7

Hi,

You should add libARMavlink in the atom.mk file.

Here is what is should look like:

ifeq ("$(TARGET_OS_FLAVOUR)","native")

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_CATEGORY_PATH := samples
LOCAL_MODULE := BebopSample
LOCAL_DESCRIPTION := Bebop sample

LOCAL_LIBRARIES := \
	libARSAL \
	libARController \
	libARDataTransfer \
	libARUtils \
	libARCommands \
	libARNetwork \
	libARNetworkAL \
	libARDiscovery \
	libARStream \
	libARStream2 \
	libARMavlink \
	ncurses

LOCAL_SRC_FILES := \
	$(call all-c-files-under,.)

include $(BUILD_EXECUTABLE)

endif

Regards,
Djavan


#8

Hi synman,

What is the MAVLINK_STORAGE_DIRECTORY used for and what is the value for it?
Do I need to create a constant variable like this
private static final File MAVLINK_STORAGE_DIRECTORY = “??”;
If so, what is the value in the ??.


#9

It’s whatever you want it to be. You still need to transfer the generated file to the drone and initiate the plan. this example merely shows you how to generate the mavlink file on your device.


#10

So if i write these it will be ok?

private static final String MAVLINK_STORAGE_DIRECTORY = "mavlink_storage_dir";

public String generateMavlinkFile(LatLng position, float altitude, float yaw) {

    final ARMavlinkFileGenerator generator;

    try {
        generator = new ARMavlinkFileGenerator();
    } catch (ARMavlinkException e) {
        Log.e(TAG, "generateMavlinkFile: " + e.getMessage(), e);
        return "";
    }

    generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkDelay(10));
    // Take off coordinates
    generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkTakeoffMissionItem((float) position.latitude, (float) position.longitude, altitude, yaw, 0));
    // Way points - coordinates to travel
    generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkNavWaypointMissionItem((float) position.latitude + 0.00002000f, (float) position.longitude + 0.00002000f, altitude, yaw));
    // Landing coordinates
    generator.addMissionItem(ARMavlinkMissionItem.CreateMavlinkLandMissionItem((float) position.latitude,(float) position.longitude, 0, 0));
    //lat,long,alt,yaw

    // save our mavlink file
    final File file = new File(MAVLINK_STORAGE_DIRECTORY);
    //noinspection ResultOfMethodCallIgnored
    file.mkdirs();

    final String filename = MAVLINK_STORAGE_DIRECTORY + File.separator + "flightPlan.mavlink";
    final File mavFile = new File(filename);

    //noinspection ResultOfMethodCallIgnored
    mavFile.delete();
    generator.CreateMavlinkFile(filename);

    return filename;
}

public void autoFlight(String filename){
    mDeviceController.getFeatureCommon().sendMavlinkStart(filename, ARCOMMANDS_COMMON_MAVLINK_START_TYPE_ENUM.ARCOMMANDS_COMMON_MAVLINK_START_TYPE_FLIGHTPLAN);
    Log.d(TAG,"sending autoFlight Mavlink file");
}

#11

the path needs to be writable… a dirty shortcut on android would be to just hardcode sdcard:

private static final String MAVLINK_STORAGE_DIRECTORY = "/sdcard/mavlink_storage_dir";

a much more robust approach would be to rely on android to determine the actual external drive path – you could also use local app storage, but I’m gathering this may be a little beyond you currently:

public static String MAVLINK_STORAGE_DIRECTORY = Environment.getExternalStorageDirectory().toString() + "/mavlink_files"

You are also still missing the actual file transfer of your flightplan mavlink file to the drone itself. sendMavlinkStart instructs the drone to execute the mavlink file loaded on its storage – not your android.


#12

Here’s how to upload:

    public void transmitMavlinkFile(final Context ctx, final ARFeatureCommon featureCommon, final ARDISCOVERY_PRODUCT_ENUM product, final String address, final String filename) {
        try {
            dataTransferManager = new ARDataTransferManager();
            uploader = dataTransferManager.getARDataTransferUploader();
            uploadManager = new ARUtilsManager();

            if (product == ARDISCOVERY_PRODUCT_ENUM.ARDISCOVERY_PRODUCT_SKYCONTROLLER_2) {
                uploadManager.initWifiFtp(UsbAccessoryMux.get(ctx).getMux().newMuxRef(), address, 61, "", "");
            } else {
                uploadManager.initWifiFtp(address, 61, "", "");
            }

            final UploadListener listener = new UploadListener(featureCommon);
            uploader.createUploader(uploadManager, "flightPlan.mavlink", filename, listener, null, listener, null, ARDATATRANSFER_UPLOADER_RESUME_ENUM.ARDATATRANSFER_UPLOADER_RESUME_FALSE);

            uploadHandlerThread = new HandlerThread("mavlink_uploader");
            uploadHandlerThread.start();

            uploadRunnable = uploader.getUploaderRunnable();
            uploadHandler = new Handler(uploadHandlerThread.getLooper());

            uploadHandler.post(uploadRunnable);

        } catch (Exception e) {
            Log.e(CLASS_NAME, "transmitMavlinkFile exception: " + e.getMessage(), e);
        }
    }

and a listener that executes sendMavlinkStart:

    private class UploadListener implements ARDataTransferUploaderProgressListener, ARDataTransferUploaderCompletionListener {

        private final ARFeatureCommon featureCommon;

        private UploadListener(final ARFeatureCommon featureCommon) {
            this.featureCommon = featureCommon;
        }

        @Override
        public void didUploadComplete(Object arg, final ARDATATRANSFER_ERROR_ENUM error) {
            if (ARPro3Application.DEBUG) Log.d(CLASS_NAME, "mavlink didUploadComplete status=" + error.name());

            final Object lock = new Object();

            synchronized (lock) {
                new Thread() {
                    @Override
                    public void run() {
                        synchronized (lock) {
                            uploader.cancelThread();
                            uploader.dispose();
                            uploader = null;

                            uploadManager.closeWifiFtp();
                            uploadManager.dispose();
                            uploadManager = null;

                            dataTransferManager.dispose();
                            dataTransferManager = null;

                            uploadHandlerThread.quit();
                            uploadHandlerThread = null;

                            if (ARPro3Application.DEBUG) Log.d(CLASS_NAME, "released uploader resources");

                            if (featureCommon != null && error == ARDATATRANSFER_ERROR_ENUM.ARDATATRANSFER_OK) {
                                if (ARPro3Application.DEBUG) Log.d(CLASS_NAME, "sendMavlinkStart");
                                featureCommon.sendMavlinkStart("flightPlan.mavlink", ARCOMMANDS_COMMON_MAVLINK_START_TYPE_ENUM.ARCOMMANDS_COMMON_MAVLINK_START_TYPE_FLIGHTPLAN);
                            }
                        }
                    }
                }.start();
            }
        }

        @Override
        public void didUploadProgress(Object arg, float percent) {
            if (ARPro3Application.DEBUG)
                Log.d(CLASS_NAME, "mavlink file upload progress=" + percent);
        }
    }
}

#13

Hi synman,

But i’m creating an android app which will transmit the mavlink file to the drone. Why do I need the Skycontroller if i’m only using my phone?


#14

The example provided will transmit your mavlink file to your drone if you are connected directly to it or indirectly through an SC1 or SC2.


#15

In my case i’m not using the skycontroller.


#16

So it will work whether it is connected to the skycontroller or not . Correct?


#17
        if (product == ARDISCOVERY_PRODUCT_ENUM.ARDISCOVERY_PRODUCT_SKYCONTROLLER_2) {
            uploadManager.initWifiFtp(UsbAccessoryMux.get(ctx).getMux().newMuxRef(), address, 61, "", "");
        } else {
            uploadManager.initWifiFtp(address, 61, "", "");
        }

Notice the else clause?


#18

What is ARPro3Application.DEBUG for? I’m having error of “Cannot resolve symbol”.
Is it a build in library function?


#19

You’re pretty new to programming.

It’s an Android application scope static boolean that determines whether anything is logged. This example is functional code part of a commercially available (production) application.


#20

Yes i’m pretty new to programming.

What is the ARFeatureCommon featureCommon used for and how do I get the value?