mavlink / MAVSDK-Java

MAVSDK client for Java.
76 stars 43 forks source link

ArduPilot SImulator Joystick Input Not Working (trying to replicate and diagnose issue with real drone in sim) #179

Open rayw-dronesense opened 2 months ago

rayw-dronesense commented 2 months ago

Environment

(2.0+ crashes with seg fault when loading camera settings on one of the physical drones, as well in some other scenarios, known separate issue reported earlier)

Background

Firstly, PX4 simulator (the Gazebo Headless one) and a PX4 based physical aircraft works perfectly fine with the existing implementation.

We now have access to a physical drone that uses ArduPilot under the hood. MAVSDK seems to be working for the most part, whereby aircraft can arm, and then I can use the left stick push upwards to take off and for the most part fly around normally using both sticks. However, when both sticks are neutral, (i.e., setManualControlInput(0f, 0f, 0.5f, 0f) is sent), the aircraft starts drifting horizontally for no apparent reason. Flight mode is being set to "Position Hold" as it should, right?

Due to risk of physical harm, we wanted to see if we can replicate it in the sim instead.

Problem

We found that while we can arm the aircraft in the ArduPilot sim using the arm function, pushing the sticks up doesn't take off.

System.manualControl.setManualControlInput(x, y, z, r)

Also tried forcing it to take off using the console, and then taking over with sticks, but the sticks still don't do anything.

rayw-dronesense commented 2 months ago

Update, managed to confirm that the physical ArduPilot-based aircraft drifting issue was fixed in MAVSDK 2.1.0. But, the ArduPilot SITL simulator still did not work - it seemed to ignore all the sticks inputs (so this ticket can still be used to fix that).

While it would be great to upgrade to 2.1.0 outright and fix the real aircraft's issue, we cannot do that due to the outstanding crash bugs in it,

rayw-dronesense commented 1 month ago

So I found out why the Sim was rejecting the Manual Control Input commands... it's being rejected by the ArduPilot side because of a sysid mismatch..

msg.sysid = 245, sysid_my_gcs = 255

This is where the ignore is happening,

void GCS_MAVLINK::handle_manual_control(const mavlink_message_t &msg)
{
    if (msg.sysid != sysid_my_gcs()) {
        GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "sysid mismatch (msg) - msg.sysid = %d, sysid_my_gcs = %d", msg.sysid, sysid_my_gcs());
        return; // only accept control from our gcs
    }

Located at https://github.com/ArduPilot/ardupilot/blob/9d6190b4fd77f28fe56851fa87f8676fb80ad1d8/libraries/GCS_MAVLink/GCS_Common.cpp#L7070

julianoes commented 1 month ago

Oh nice find. How do you set ArduPilot to accept commands from 245?

If not, you have to set MAVSDK's sysid here: https://github.com/mavlink/MAVSDK/blob/0b564f0deef4d6a67e6b542ec10c59cc0b33f482/src/mavsdk_server/src/mavsdk_server_api.h#L30

rayw-dronesense commented 1 month ago

Oh, I didn't realize you could set the sysid from the SDK side, thanks for that reference.

I ended up commenting out the return linked above to get the sim past that.

Then it started showing the "Throttle not zero" and "RC XYZ too high" errors preventing the Sim from arming (which is same behavior as QGC). I ended up commenting out those checks in ArduCopter/AP_Arming.cpp to get past those. Then I was able to fully use the manual control inputs from SDK in the ArduPilot Sim.

Very strange why it behaves like this out of the box.

Again, the real physical ArduPilot-based drone doesn't do this....only the simulator.

rayw-dronesense commented 1 month ago

@julianoes Update: it turns out I was wrong, even the real drone was rejecting the manual input commands; it just so happened to work because the system had a built in mechanism that forwards the physical stick inputs to the drone outside of any apps running.

I haven't yet tried the mavsdk_server_run_with_mavlink_ids API, but I did try changing the hardcoded 245 value in DEFAULT_GCS_SYSTEM to 255 and that made it work in both the sim and the real drone.

I was able to get around the "throttle not zero" error by forcing it to send 0,0,0,0 for the inputs when the aircraft isn't armed and we are trying to arm. And send real values after it's armed.

rayw-dronesense commented 1 month ago

Another update: can confirm, changing the MAVSDK-Java - Server .cpp nativeLib to use mavsdk_server_run_with_mavlink_ids and sending 255 and 190 for system and component ID respectively also worked.

julianoes commented 1 month ago

Yay nice! What should we do? Maybe add a note in the docs regarding this?

julianoes commented 1 month ago

Or in the docstring of the API itself?

rayw-dronesense commented 1 month ago

@julianoes Hmm...I'm not sure, what would the impact be of just changing the hardcoded DEFAULT GCS ID to 255 in the SDK, would that break compatibility with any existing drones that already work? Because if it doesn't, then this would only increase the number of compatible drones (namely Ardu based ones)?

What would you suggest as being the best option that will allow the SDK to work with the most drones?

julianoes commented 1 month ago

The problem is that it would conflict with QGC for most setups and cause havoc like that.

System IDs can be selected arbitrarily, so ArduPilot should not be make any hard-coded assumptions, in my opinion.

rayw-dronesense commented 1 month ago

@julianoes That's great to know; so if the purpose of bringing in the SDK is replacing QGC entirely, it would be safe / compatible to use the 255 ID with any MAVLink aircraft?

If so, perhaps we could introduce some sort of API on the Java side that would activate "QGC replacement mode" or whatever which will use these IDs? Because right now the only way to set these IDs is to make modifications to the MAVSDK-Java-Server library and doing a local AAR build.

A bit of documentation explaining why this is needed would be helpful too of course.

rayw-dronesense commented 1 month ago

System IDs can be selected arbitrarily, so ArduPilot should not be make any hard-coded assumptions, in my opinion.

We could probably file a bug against ArduPilot to have them change this, but that would only help for future aircraft not already-deployed ones, right? 😁

julianoes commented 1 month ago

As long as no QGC (or MissionPlanner?) system is suddenly added to the mix, it should work. I can't really vouch for something to be "safe" as your own testing has to determine that.

Now regarding the APIs: I'm not against exposing these arguments further out, so that you don't have to re-compile the mavsdk_server stuff. Feel free to make a pull request for that.

I would at least ask the ArduPilot community why that is the way it is and whether it could be changed. By the way, this probably touches the broader "who is in control" discussion that we're having here: https://github.com/mavlink/mavlink/issues/2098

julianoes commented 1 month ago

@rayw-dronesense I brought this up in the call and it turns out there is an ArduPilot param to set: https://ardupilot.org/copter/docs/parameters.html#sysid-mygcs-my-ground-station-number

rayw-dronesense commented 1 month ago

@julianoes Nice find! Though if we set that, it would break the aircraft's compatibility with QGC right? (should the user choose to switch over to using QGC)

julianoes commented 1 month ago

You can also set QGC's system ID to something else if you want to.

rayw-dronesense commented 1 day ago

Hmm...I think the best solution here might be to expose another Java API parameter that lets clients customize the system ID then