mavlink / MAVSDK-Java

MAVSDK client for Java.
68 stars 40 forks source link

Mission files cannot be sent over serial #106

Open jankrystianserafim opened 1 year ago

jankrystianserafim commented 1 year ago

Good afternoon , Hopefully you guys can help me a bit with this problem:) In my Android app, I am using the mavsdk command to upload a mission file (for example a .plan file that is being stored inside my app as a json file). This command is working perfectly well (the mission file is being uploaded to the drone successfully) when I am connecting my telemetry radio to my laptop and using the mavsdkserver version that I am running from command line (using this command: mavsdk_server_win32.exe serial://COM14:115200) and telling my Android app that mavsdkserver is at the IP address of my laptop. But then the exact same command and the exact same code is not working (upload failed - the drone does not successfully receive the mission file) when I am connecting my telemetry radio to my Android tablet instead of my laptop and using the mavsdkserver versionn that is provided by mavsdk in the Android app (in the gradle files, as io.mavsdk:mavsdk-server:1.1.1). Do you have any idea what is causing the problem here? Is the version of mavsdkserver used by Android app's different than mavsdk_server_win32.exe? Does the mavsdkserver version for Android not yet support uploading mission files? Thanks!

JonasVautherin commented 1 year ago

Could this be related to https://github.com/mavlink/MAVSDK-Java/issues/23? Unfortunately I never had time to look into it myself, but there is a pretty big discussion there that I believe could help :+1:

jankrystianserafim commented 1 year ago

@JonasVautherin I do not think so. My Android app is running on an Android tablet, and connecting with the drone using serial communication via a telemetry radio connected by USB cable to the tablet. Commands like arm, disarm, start mission (so the drone starts doing the mission that has already been pre-loaded onto the drone using e.g. mission planner), or getting telemetry information are all working perfectly fine and in real time. It is just this command "uploadGeneratedRawMission that is not working, when we try and use it to upload the json file with the mission for the drone.

jankrystianserafim commented 1 year ago

PS- I could provide the code that we are using to upload the mission file if that helps?

JonasVautherin commented 1 year ago

How does it fail? Is it a timeout?

jankrystianserafim commented 1 year ago

So actually there are no errors shown in logcat other than this here, whis is simply a log message "Failed upload" that we added in the code that is shown if the RxJava doOnError method is called from the uploadMission() function image

JonasVautherin commented 1 year ago

What is the exception you get in doOnError, then?

jankrystianserafim commented 1 year ago

I can just share our code for this with you:

` List missionItems = new ArrayList<>(); missionItems.addAll(cycle);

    Log.d(TAG,"About to upload " + missionItems.size() + " mission items...");
    mDrone.getMissionRaw()
            .uploadMission(cycle)
            .doOnComplete(() -> {
                Log.d(TAG,"Uploaded.");

            })
            .doOnError(throwable -> {
                Log.d(TAG,"Failed upload.");

            })
            .subscribe(latch::countDown, throwable -> latch.countDown());

    try {
        latch.await();

    } catch (InterruptedException ignored) {
        Toast.makeText(mAppContext, "Upload Failed", Toast.LENGTH_SHORT).show();
        // This is expected
    }

} else {
    Toast.makeText(mAppContext, "Not Connected", Toast.LENGTH_SHORT).show();
    mPositionLiveData = null;
}
}`
JonasVautherin commented 1 year ago
.doOnError(throwable -> {
    Log.d(TAG,"Failed upload.");
})

throwable is an Exception? What's its type, and what message does it give you? Here you lose the information by just printing "Failed upload".

ThomasCarstens commented 1 year ago

Hi @JonasVautherin so we did check the error ( I'm working with @jankrystianserafim ). It's a MissionRawException: INVALID_ARGUMENT. We tested the unhandled version and you can see it below. Just to recap the situation, this error does not appear with the mavserver on PC, ie.

It appears however when everything is the same except the Mavserver is started on Android (v.1.1.1). Once again, connected via serial to the drone, with a physical phone. The only difference seems to be the Mavserver in-app vs on pc. All other commands (connect, arm, etc) still work however. I wondered if mission size had an effect, but with 2 items, the upload still fails, yet it works when mavserver is on PC.

Here's the unhandled error:

2022-08-14 21:12:32.141 30182-32556/com.app.myapp E/AndroidRuntime: FATAL EXCEPTION: grpc-default-executor-1
    Process: com.app.myapp, PID: 30182
    io.reactivex.exceptions.OnErrorNotImplementedException: The exception was not handled due to missing onError handler in the subscribe() method call. Further reading: https://github.com/ReactiveX/RxJava/wiki/Error-Handling | io.mavsdk.mission_raw.MissionRaw$MissionRawException: INVALID_ARGUMENT: Invalid Argument
        at io.reactivex.internal.observers.EmptyCompletableObserver.onError(EmptyCompletableObserver.java:50)
        at io.reactivex.internal.operators.completable.CompletablePeek$CompletableObserverImplementation.onError(CompletablePeek.java:95)
        at io.reactivex.internal.operators.completable.CompletablePeek$CompletableObserverImplementation.onError(CompletablePeek.java:95)
        at io.reactivex.internal.operators.completable.CompletableSubscribeOn$SubscribeOnObserver.onError(CompletableSubscribeOn.java:74)
        at io.reactivex.internal.operators.completable.CompletableCreate$Emitter.tryOnError(CompletableCreate.java:90)
        at io.reactivex.internal.operators.completable.CompletableCreate$Emitter.onError(CompletableCreate.java:76)
        at io.mavsdk.mission_raw.MissionRaw$1.onNext(MissionRaw.java:449)
        at io.mavsdk.mission_raw.MissionRaw$1.onNext(MissionRaw.java:442)
        at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onMessage(ClientCalls.java:466)
        at io.grpc.internal.DelayedClientCall$DelayedListener.onMessage(DelayedClientCall.java:447)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInternal(ClientCallImpl.java:661)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInContext(ClientCallImpl.java:646)
        at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
        at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
     Caused by: io.mavsdk.mission_raw.MissionRaw$MissionRawException: INVALID_ARGUMENT: Invalid Argument
        at io.mavsdk.mission_raw.MissionRaw$1.onNext(MissionRaw.java:449) 
        at io.mavsdk.mission_raw.MissionRaw$1.onNext(MissionRaw.java:442) 
        at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onMessage(ClientCalls.java:466) 
        at io.grpc.internal.DelayedClientCall$DelayedListener.onMessage(DelayedClientCall.java:447) 
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInternal(ClientCallImpl.java:661) 
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInContext(ClientCallImpl.java:646) 
        at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) 
        at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:923) 
2022-08-14 21:12:32.386 30182-30182/com.app.myapp E/libprocessgroup: set_timerslack_ns write failed: Operation not permitted
JonasVautherin commented 1 year ago

Which version of mavsdk_server are you running in Android?

InvalidArgument is sent from this file, I would say: https://github.com/mavlink/MAVSDK/blob/main/src/mavsdk/plugins/mission_raw/mission_raw_impl.cpp. Maybe you can try to debug it there to see precisely why mavsdk_server complains about your arguments?

jankrystianserafim commented 1 year ago

mavsdk_server and mavsdk versions are both 1.1.1

How can I try and debug it there?

jankrystianserafim commented 1 year ago

@JonasVautherin Quick question. When I generate a .plan file using the desktop version of QGC, then open it in a text editor (e.g. Notepad), and I copy and paste the text from the .plan file into a string array in Java, is that a missionraw file? In other words, is a .plan file generated by QGC = missionraw file ?

JonasVautherin commented 1 year ago

How can I try and debug it there?

You can try to run mavsdk_server on your laptop and connect your Android app to it (instead of running MavsdkServer inside your app). If that's not enough, you can add some debug output to mavsdk_server and recompile it (using the Gradle composite builds should help, see here).

jankrystianserafim commented 1 year ago

So we've already tried running mavskd_server on my laptop and connecting our Android app to it (we just say in the app that the system is at the IP address of the laptop). I will also add some debug outputs.

JonasVautherin commented 1 year ago

And can you reproduce the issue with this setup?

jankrystianserafim commented 1 year ago

Yes, exactly the same issue. I also discussed this issue with Julian (@julianoes), and we both think that it may be something to do with the import_qgroundcontrol_mission() function https://mavsdk.mavlink.io/main/en/cpp/api_reference/classmavsdk_1_1_mission_raw.html#classmavsdk_1_1_mission_raw_1a43345b21cf9dedf594f62ec7ad963ce8 . If you want I can share with you the repository on Github that I have prepared for debugging this issue? We are working there with Julian.