mavlink / MAVSDK-Java

MAVSDK client for Java.
68 stars 40 forks source link

Implemented a new internal initialization mechanism for the library. #81

Closed divyanshupundir closed 2 years ago

divyanshupundir commented 2 years ago

Problem

mavsdk-server version 0.11.0 blocks the calling thread while discovering a system. This creates a problem for Android as the UI thread cannot be blocked. Simply pushing the mavsdk-server to the background does not work because the plugins require the gRPC server on the mavsdk-server to be running (which will happen only if a system is discovered). As a result, the users of the library need to implement tedious workarounds to make things work.

The idea behind this PR is to make the library handle the initialization problems so that the users need to make minimal changes to their codebases which were written using the SDK version including and prior to 0.10.0.

Solution

This PR tackles the problem by:

  1. Introducing a dedicated thread mavsdk-event-queue for initializing and disposing the mavsdk-server/plugins/infinite streams.
  2. Decoupling plugin construction and initialization.

For Android, the only change the users need to make is to execute MavsdkServer.run() method in the mavsdk-event-queue as follows:

MavsdkEventQueue.executor().execute(() -> mavsdkServer.run("localhost", PORT));

Internally, plugins are constructed lazily through the io.mavsdk.System instances. Upon their first call, their initialization commands are added to the mavsdk-event-queue. Notice that these executions will be blocked in the mavsdk-event-queue until the server discovers a system.

Infinite streams (eg. Telemetry.Position) are handled similarly.

One-shot calls like takeoff, land and upload mission are not added to the mavsdk-event-queue when the user subscribes to them. This is done to avoid their piling up while the mavsdk-server discovers a system. Instead, the onError callback will be triggered after a 100ms delay indicating that no system was available for the command.

Other additions

  1. Added the io.mavsdk.Plugin interface, which is implemented by all the plugins.
  2. Added the io.mavsdk.MavsdkException to differentiate between exceptions thrown by MAVSDK and other components like SocketException which may be thrown by gRPC.
  3. Plugins are lazily initialized upon their first call so that the users don't have to pay for the plugins that they won't use.

Update

  1. Updated the protoc codegen toolchain which resolves the duplicate class found problem mentioned in #79.
JonasVautherin commented 2 years ago

Looks nice! :rocket:

I'll have to go through the code again and try it myself, but that looks good! Thanks a lot!

divyanshupundir commented 2 years ago

@JonasVautherin, have you had a chance to go through the code and test it? I have been testing it extensively using SITL. But not as much as I would like on hardware. By the end of December, I would have done more thorough tests.

For now, I haven't been facing any issues.

divyanshupundir commented 2 years ago

I have been testing it on hardware for some time. I haven't been facing any issues.

divyanshupundir commented 2 years ago

Thanks for the review.